Kate’s DVG code
message("Loading packages")
Loading packages
library('ggplot2')
library('readr')
library('reshape2')
library('ggpubr')
library('plyr')
Attaching package: ‘plyr’
The following object is masked from ‘package:ggpubr’:
mutate
library('tidyverse')
── Attaching core tidyverse packages ───────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.0 ✔ stringr 1.5.0
✔ forcats 1.0.0 ✔ tibble 3.1.8
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.1 ── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::arrange() masks plyr::arrange()
✖ purrr::compact() masks plyr::compact()
✖ dplyr::count() masks plyr::count()
✖ dplyr::desc() masks plyr::desc()
✖ dplyr::failwith() masks plyr::failwith()
✖ dplyr::filter() masks stats::filter()
✖ dplyr::id() masks plyr::id()
✖ dplyr::lag() masks stats::lag()
✖ dplyr::mutate() masks plyr::mutate(), ggpubr::mutate()
✖ dplyr::rename() masks plyr::rename()
✖ dplyr::summarise() masks plyr::summarise()
✖ dplyr::summarize() masks plyr::summarize()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library('dplyr')
library('glue')
library('ggVennDiagram')
# paramters used when running divrge
grouping_param = 5
match_length_param = 28
readLength = 150
# deletion read count cutoffs
count_cut = 30
# only looking at index and direct cases
keeping = c('index','direct')
message("Setting work directory and input file names")
Setting work directory and input file names
wkdir = "/Users/marissaknoll/Desktop/GitHub/Obesity/NewExtractions/H9N2/DVGs"
setwd(wkdir)
if (!dir.exists(glue("{wkdir}/DVG_figures"))) {
dir.create(glue("{wkdir}/DVG_figures"))
}
saveitdir = glue("{wkdir}/DVG_figures")
source(glue('{wkdir}/scripts/obese_PlotPrep.R'))
# loading in metadata and coverage data
metafile = glue("{wkdir}/scripts/transmission_h9n2_use_long.csv")
meta = read.csv(file=metafile,header=T,sep=",",na.strings = c(''))
meta = filter(meta, flag == "keep")
coverage_passfile = glue('{wkdir}/scripts/H9N2.coverage.pass.check.200.0.95.csv')
cov_check = read.csv(file=coverage_passfile,header=T,sep=",",na.strings = c(''))
# filter for samples that either pass with a yes OR has good average coverage and percentage cov at 200x is > 80
cov_filt_names = cov_check %>% filter(pass == 'YES' |
mean_coverage >= 200 |
percentage > 0.7) %>%
select(name, segment) %>%
unique()
cov_filt_names = filter(cov_filt_names, name != "2244_d12") %>% unique()
# check segment count
cov_filt_names = cov_filt_names %>% group_by(name) %>% add_tally(name = 'segment_tally') %>%
ungroup() %>%
filter(segment_tally == 8) %>%
unique()
pull_names = c(levels(factor(cov_filt_names$name))) # list to pull names from
dvgfile = glue('{wkdir}/H9N2.DVG.FINAL.OneGap.N5.Mis2.M28.G5.csv') # dvg file
dvg = read.csv(file=dvgfile,header=T,sep=",",na.strings = c(''))
dvg = dvg %>% filter(name %in% pull_names) # filter for samples that pass our coverage checks
dvg$sample = dvg$name # generate new column so we can separate
dvg = dvg %>% separate(sample, c('new','cohort','ferret_id','dpi','rep'), '_') # separate into info
Warning: Expected 5 pieces. Missing pieces filled with `NA` in 40841 rows [200533, 200534, 200535, 200536, 200537, 200538, 200539, 200540, 200541, 200542, 200543, 200544, 200545, 200546, 200547, 200548, 200549, 200550, 200551, 200552, ...].
CONTROLS = dvg %>% filter(ferret_id == 'HK1073') # pulling out controls
CONTROLS$rep = CONTROLS$dpi
CONTROLS$dpi = 'stock' # adding in stock info
dvg = dvg %>% filter(!name %in% c(levels(factor(CONTROLS$name)))) %>% unique()
dvg = rbind(dvg, CONTROLS) # rbind everything so it is all in one dataframe
# prepping rep information
dvg = dvg %>% select(-SegTotalDVG) %>% filter(DVG_freq >= count_cut) %>% unique() # filter for those that pass cutoffs
rep1 = dvg %>% filter(rep == 'rep1') %>% unique()
rep2 = dvg %>% filter(rep == 'rep2') %>% unique()
# merge reps into one
dvg_reps = merge(rep1, rep2, by = c('cohort','ferret_id','dpi',
'segment','segment_size','strain',
'DVG_group','NewGap',
'NewStart','NewEnd','GroupBoundaries',
'DeletionSize','EstimatedFragLength'), all = TRUE) %>% unique()
# add in zeros
dvg_reps$DVG_freq.x[is.na(dvg_reps$DVG_freq.x)] = 0
dvg_reps$DVG_freq.y[is.na(dvg_reps$DVG_freq.y)] = 0
ggplot(dvg_reps, aes(x=DVG_freq.x, y=DVG_freq.y)) +
geom_point() +
PlotTheme1

# number of samples?
levels(factor(dvg_reps$ferret_id)) %>% length()
[1] 42
# reorder by segment size
SEGMENTS = c('H9N2_PB2', 'H9N2_PB1',
'H9N2_PA','H9N2_HA','H9N2_NP',
'H9N2_NA','H9N2_MP','H9N2_NS')
cov_check$segment = factor(cov_check$segment, levels = SEGMENTS)
cov_check %>%
filter(name %in% pull_names) %>%
ggplot(., aes(x= segment, y = mean_coverage)) +
geom_boxplot() +
PlotTheme1

cov_check %>%
filter(name %in% pull_names) %>%
ggplot(., aes(x= segment, y = median_coverage)) +
geom_boxplot() +
PlotTheme1

cov_check %>%
filter(name %in% pull_names) %>%
ggplot(., aes(x= segment, y = percentage)) +
geom_boxplot() +
PlotTheme1

df = cov_filt_names %>% select(-segment, -segment_tally) %>% unique()
df$sample = df$name
df = df %>% separate(sample, c('new','cohort','ferret_id','dpi','rep'), '_')
Warning: Expected 5 pieces. Missing pieces filled with `NA` in 10 rows [34, 35, 49, 71, 84, 153, 165, 170, 187, 201].
CONTROLS = df %>% filter(ferret_id == 'HK1073')
CONTROLS$rep = CONTROLS$dpi
CONTROLS$dpi = 'stock'
df = df %>% filter(!name %in% c(levels(factor(CONTROLS$name)))) %>% unique()
df = rbind(df, CONTROLS)
r1 = df %>% filter(rep == 'rep1') %>% select(-new) %>% unique()
r2 = df %>% filter(rep == 'rep2') %>% select(-new) %>% unique()
reps = merge(r1, r2, by = c('cohort','ferret_id','dpi')) %>% unique()
# these are the samples that only had one rep!
setdiff(levels(factor(r1$ferret_id)),
levels(factor(r2$ferret_id)))
[1] "1411" "1972" "2244"
setdiff(meta$ferret_id, reps$ferret_id) # samples in meta not in seq data
[1] "1793" "1803" "1788" "1805" "1795" "1790" "1796" "1911" "1982" "1978" "1985" "1979" "1971" "1987" "1967" "1976" "1915" "2230" "2235" "2237"
[21] "2242" "2241" "2238"
setdiff(reps$ferret_id, meta$ferret_id) # samples in seq data not in meta
[1] "1966" "1969" "1968" "2243" "1408" "1409" "1410" "1412" "1414" "1415" "1416" "1417"
m = merge(reps, meta, by = c('ferret_id'), all = TRUE)
write.csv(m, glue('{wkdir}/scripts/UPDATED.H9N2.metadata.csv'), row.names = FALSE)
temp = meta %>%
filter(type %in% c('index','direct')) %>%
unique() %>%
select(pair, type, ferret_id) %>% unique() %>%
pivot_wider(names_from = 'type', values_from = 'ferret_id')
temp = rbind(temp, c('Z','stock','stock'))
temp$pair_ids = paste0(temp$index,'>',temp$direct)
temp = temp %>% select(pair, pair_ids) %>% unique()
m = merge(m, temp, by = c('pair')) # add in additional information to metadata to work with
# type check - only stock index direct
print(levels(factor(m$type)))
[1] "aerosol" "direct" "index" "secondary" "stock"
m$type = factor(m$type, levels = c('stock','index','direct'))
m = m %>% filter(name.x != is.na(name.x)) %>% unique()
p1 = m %>% filter(ferret_id != 'HK1073') %>% unique() %>%
ggplot(., aes(x= dpi, y = pair_ids, fill = ferret_weight)) +
geom_tile(color = 'black') +
PlotTheme3 +
weight_colFill +
facet_grid(index_direct~type, scales = 'free', space = 'free')
print(p1)
ggsave(p1,
filename = glue("{wkdir}/DVG_figures/final.samples.pdf"),
width = 6,
height = 6, limitsize=FALSE, useDingbats = FALSE)
ggsave(p1,
filename = glue("{wkdir}/DVG_figures/final.samples.png"),
width = 6,
height = 6, limitsize=FALSE) #, useDingbats = FALSE)

dvg_reps = dvg_reps %>%
filter(DVG_freq.x > count_cut & DVG_freq.y > count_cut) %>%
unique() # make sure that both reps pass our cutoff
# add in variables for plotting
dvg_reps$ferret_day = paste0(dvg_reps$ferret_id, '_', dvg_reps$dpi)
m$ferret_day = paste0(m$ferret_id, '_', m$dpi)
stock_temp = dvg_reps %>% filter(dpi == 'stock') %>%
group_by(ferret_id, cohort, dpi, segment, name.x, name.y) %>%
add_tally(name = 'seg_deletion_richness') %>%
unique() %>%
ungroup() %>%
group_by(ferret_id, dpi, name.x, name.y, cohort) %>%
add_tally(name = 'deletion_richness') %>%
ungroup() %>%
unique()
s = stock_temp # will use later
# filter down stock temp information
stock_temp = stock_temp %>%
select(ferret_id, dpi, cohort,ferret_day, segment, deletion_richness, seg_deletion_richness) %>%
unique()
stock_temp = merge(stock_temp, m, by = c('ferret_id', 'dpi','cohort','ferret_day')) %>%
unique()
# filter out stock information, calculate dvg richness by segment and across genome for samples
dr = dvg_reps %>%
filter(dpi != 'stock') %>%
unique() %>%
group_by(ferret_id, dpi, segment, name.x, name.y, cohort) %>%
add_tally(name = 'seg_deletion_richness') %>%
ungroup() %>%
group_by(ferret_id, dpi, name.x, name.y, cohort) %>%
add_tally(name = 'deletion_richness') %>%
ungroup() %>%
unique()
# filter down information so you don't have duplicates
richness = dr %>%
select(ferret_id, dpi, cohort,ferret_day, segment, deletion_richness, seg_deletion_richness) %>%
unique()
# merge with metadata info
richness = merge(richness, m, by = c('ferret_id', 'dpi','cohort','ferret_day'), all.y = TRUE) %>%
unique()
# make sure we filter out stock information (will add using the 's' dataframe generated above)
richness = richness %>% filter(dpi != 'stock')
reps_df = rbind(dr, s) # final reps richness df
reps_df = merge(reps_df, m, by = c('ferret_id','dpi','cohort','ferret_day')) # add metadata
p4 = reps_df %>%
select(segment, NewGap, EstimatedFragLength, ferret_weight) %>%
unique() %>%
ggplot(., aes(x= EstimatedFragLength)) +
geom_histogram(color = 'black') +
PlotTheme1 +
labs(x="estimated DVG frag. length (nt)", y='number of unique DVG species')
print(p4)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/deletion.size.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/deletion.size.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

p4_alt = reps_df %>%
select(segment, NewGap, EstimatedFragLength, ferret_weight, type) %>%
unique() %>%
ggplot(., aes(x= EstimatedFragLength)) +
geom_histogram(color = 'black', binwidth = 50) +
facet_grid(type~ferret_weight) +
PlotTheme1 +
labs(x="estimated DVG frag. length (nt)", y='number of unique DVG species')
print(p4_alt)
ggsave(p4_alt,
filename = glue("{wkdir}/DVG_figures/deletion.size.bydiet.bytype.pdf"),
width = 10,
height = 5, limitsize=FALSE, useDingbats = FALSE)

lean_index = reps_df %>% filter(type == 'index' & ferret_weight == 'lean') %>%
unique() %>%
group_by(NewGap, segment, NewStart, NewEnd) %>%
add_tally(name = 'lean_deletion_count') %>%
ungroup() %>%
select(NewGap, segment, lean_deletion_count) %>%
unique()
obese_index = reps_df %>% filter(type == 'index' & ferret_weight == 'obese') %>%
unique() %>%
group_by(NewGap, segment, NewStart, NewEnd) %>%
add_tally(name = 'obese_deletion_count') %>%
ungroup() %>%
select(NewGap, segment, obese_deletion_count) %>%
unique()
df = merge(lean_index, obese_index, by = c('NewGap','segment'), all = TRUE)
head(df)
df$lean_deletion_count[is.na(df$lean_deletion_count)] = 0
df$obese_deletion_count[is.na(df$obese_deletion_count)] = 0
p8 = reps_df %>% filter(type == 'index') %>%
unique() %>%
group_by(NewGap, segment, NewStart, NewEnd) %>%
add_tally(name = 'sample_count') %>%
ungroup() %>%
select(NewGap, segment,sample_count) %>%
unique() %>%
ggplot(., aes(x=sample_count, y = ..count../sum(..count..))) +
geom_histogram(color ='black') +
labs(x='number of samples with DVG type', y='proportion of DVGs in dataset (index only)') +
PlotTheme1
print(p8)
ggsave(p8,
filename = glue("{wkdir}/DVG_figures/sample.count.histo.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p8,
filename = glue("{wkdir}/DVG_figures/sample.count.histo.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

reps_df$ave_dvg_freq = (reps_df$DVG_freq.x + reps_df$DVG_freq.y)/2
reps_df = reps_df %>%
arrange(ferret_day, ave_dvg_freq) %>%
group_by(ferret_day) %>%
mutate(order_number = row_number()) %>%
ungroup() %>%
unique()
reps_df %>%
group_by(NewGap, segment, type, ferret_weight) %>%
mutate(mean_order = mean(order_number),
sample_count = n(),
min_order = min(order_number),
max_order = max(order_number),
median_ord = median(order_number)) %>%
ungroup() %>%
unique() %>%
select(segment, NewGap, mean_order, sample_count, min_order, max_order, median_ord, type, ferret_weight) %>%
filter(sample_count > 1) %>%
unique() %>%
ggplot(., aes(y=mean_order, x = sample_count)) +
geom_point() +
PlotTheme1 +
facet_grid(.~ferret_weight + type)

top_ten = reps_df %>% filter(order_number %in% c(1, 2,3 ,4, 5, 6, 7, 8, 9, 10)) %>% unique()
head(top_ten)
length(levels(factor(top_ten$NewGap)))
[1] 361
max(df$lean_deletion_count)
[1] 19
max(df$obese_deletion_count)
[1] 13
p9 = ggplot(df, aes(x=lean_deletion_count, y = obese_deletion_count)) +
geom_jitter(width = 0.1, height = 0.1, alpha = 0.3) +
geom_hline(yintercept = 0, linetype = 2, color = 'black') +
geom_hline(yintercept = 25, linetype = 2, color = 'red') +
geom_vline(xintercept = 0, linetype = 2, color = 'black') +
geom_vline(xintercept = 17, linetype = 2, color = 'red') +
labs(x= 'number of lean samples with DVG', y='number of obese samples with DVG') +
PlotTheme1
print(p9)
ggsave(p9,
filename = glue("{wkdir}/DVG_figures/sample.count.lean.v.obese.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p9,
filename = glue("{wkdir}/DVG_figures/sample.count.lean.v.obese.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

reps_df %>% filter(type == 'index' & ferret_weight == 'obese') %>% select(name.x.x) %>% unique() %>% nrow()
[1] 13
reps_df %>% filter(type == 'index' & ferret_weight == 'lean') %>% select(name.x.x) %>% unique() %>% nrow()
[1] 20
richness = rbind(richness, stock_temp)
richness$deletion_richness[is.na(richness$deletion_richness)] = 0
DAYS = c('stock','d02','d04','d06','d08','d10','d12')
richness$cohort = gsub("FCC","Sp19",richness$cohort)
richness$dpi = factor(richness$dpi, levels = DAYS)
richness %>% filter(dpi %in% c('d02','d04')) %>%
filter(type == 'index' | type == 'stock') %>%
select(ferret_id, dpi, deletion_richness, type, ferret_weight, index_direct, cohort) %>%
unique() %>%
group_by(ferret_id) %>%
add_tally(name = 'n') %>%
ungroup() %>%
filter(n >= 2) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=dpi, y = deletion_richness, color = cohort, group=ferret_id, shape = ferret_weight)) +
#geom_boxplot() +
geom_line() +
geom_point(size = 2) +
PlotTheme1 +
scale_color_brewer(palette = 'Set1')

#weight_colScale +
#facet_grid(.~cohort)
p7 = richness %>% filter(dpi %in% c('d02','d04','d06')) %>%
filter(type == 'index' | type == 'stock') %>%
select(ferret_id, dpi, deletion_richness, type, ferret_weight, index_direct, cohort) %>%
unique() %>%
group_by(ferret_id) %>%
add_tally(name = 'n') %>%
ungroup() %>%
filter(n >= 2) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=dpi, y = deletion_richness, color = ferret_weight, group=ferret_id, shape = ferret_weight)) +
#geom_boxplot() +
geom_line() +
geom_point(size = 2) +
PlotTheme1 +
weight_colScale
#facet_grid(.~cohort)
print(p7)
ggsave(p7,
filename = glue("{wkdir}/DVG_figures/richness.index.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p7,
filename = glue("{wkdir}/DVG_figures/richness.index.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

colnames(richness)
[1] "ferret_id" "dpi" "cohort" "ferret_day" "segment"
[6] "deletion_richness" "seg_deletion_richness" "pair" "name.x" "rep.x"
[11] "name.y" "rep.y" "ferret_weight" "type" "flag"
[16] "chain_position" "notes" "index_direct" "worked" "pair_ids"
order_typeday = c('stock','index_d02','index_d04',
'index_d06','index_d08','index_d10',
'index_d12',
'direct_d02','direct_d04',
'direct_d06','direct_d08','direct_d10',
'direct_d12')
richness$type_day = paste0(richness$type, '_', richness$dpi)
richness$type_day = factor(richness$type_day, levels = order_typeday)
p2 = richness %>% filter(ferret_weight == 'obese' & index_direct == 'obese_obese') %>%
select(ferret_id, dpi, deletion_richness, type, ferret_weight,
pair_ids, index_direct, type_day) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=type_day, y = deletion_richness, color = pair_ids, group=pair_ids)) +
#geom_boxplot() +
geom_line(size = 1) +
geom_point(size = 2) +
labs(x='dpi (by index case)', y='DVG richness') +
PlotTheme1 +
scale_color_brewer(palette = 'Set2') #+
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.
#weight_colScale +
#facet_grid(.~type)
print(p2)
ggsave(p2,
filename = glue("{wkdir}/DVG_figures/obese.to.obese.diversity.pdf"),
width = 8,
height = 6, limitsize=FALSE, useDingbats = FALSE)
ggsave(p2,
filename = glue("{wkdir}/DVG_figures/obese.to.obese.diversity.png"),
width =8,
height = 6, limitsize=FALSE) #, useDingbats = FALSE)

gen_rich = richness %>%
select(ferret_id, dpi, cohort,deletion_richness, type, ferret_weight, pair_ids, index_direct, type_day) %>%
unique()
head(gen_rich)
gen_rich %>% filter(dpi %in% c('d02','d04','d06','stock')) %>%
filter(type == 'index' | type == "stock") %>%
ggplot(., aes(x=ferret_weight, y = deletion_richness, group = ferret_weight)) +
geom_boxplot(outlier.shape = NA) +
geom_jitter(width = 0.2, aes(color = ferret_weight)) +
labs(x='segment',y='deletion richness') +
PlotTheme1 +
weight_colScale +
facet_grid(.~dpi)

Test for significance
o = filter(gen_rich, type == "index" & dpi == "d06" & ferret_weight == "obese")
l = filter(gen_rich, type == "index" & dpi == "d06" & ferret_weight == "lean")
t.test(o$deletion_richness,l$deletion_richness)
Welch Two Sample t-test
data: o$deletion_richness and l$deletion_richness
t = -0.91173, df = 4.5571, p-value = 0.4076
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-106.18666 51.78666
sample estimates:
mean of x mean of y
34.0 61.2
seg_rich = richness %>% #filter(ferret_weight == 'obese' & index_direct == 'obese_obese') %>%
select(ferret_id, dpi, seg_deletion_richness, type, ferret_weight,
pair_ids, index_direct, type_day, segment) %>%
unique()
head(seg_rich)
temp = seg_rich %>% select(ferret_id, dpi, type, ferret_weight, pair_ids, type_day, index_direct) %>% unique()
temp$H9N2_PB2 = 0
temp$H9N2_PB1 = 0
temp$H9N2_PA = 0
temp$H9N2_HA = 0
temp$H9N2_NP = 0
temp$H9N2_NA = 0
temp$H9N2_MP = 0
temp$H9N2_NS = 0
temp = pivot_longer(temp, cols = all_of(SEGMENTS), names_to = 'segment') %>% select(-value)
seg_rich = merge(seg_rich, temp, by = c('ferret_id', 'dpi', 'type', 'ferret_weight',
'pair_ids', 'index_direct', 'type_day', 'segment'), all = TRUE)
seg_rich$seg_deletion_richness[is.na(seg_rich$seg_deletion_richness)] = 0
seg_rich$segment = factor(seg_rich$segment, levels = SEGMENTS)
head(seg_rich)
p3 = seg_rich %>% filter(segment %in% SEGMENTS) %>%
ggplot(., aes(x=segment, y = seg_deletion_richness)) +
geom_boxplot() +
labs(x='segment',y='deletion richness') +
PlotTheme1
print(p3)
ggsave(p3,
filename = glue("{wkdir}/DVG_figures/segment.richness.pdf"),
width = 5,
height = 5, limitsize=FALSE, useDingbats = FALSE)
ggsave(p3,
filename = glue("{wkdir}/DVG_figures/segment.richness.png"),
width =5,
height = 5, limitsize=FALSE) #, useDingbats = FALSE)

seg_rich$seg_weight = paste0(seg_rich$segment, '_', seg_rich$ferret_weight)
seg_rich$ferret_weight = factor(seg_rich$ferret_weight, levels = c('stock','lean','obese'))
seg_rich %>% filter(segment %in% SEGMENTS) %>%
ggplot(., aes(x=segment, y = seg_deletion_richness, group = seg_weight, color = ferret_weight)) +
geom_boxplot() +
labs(x='segment',y='deletion richness') +
PlotTheme1 +
weight_colScale +
facet_grid(.~type)

p6 = seg_rich %>% filter(segment %in% SEGMENTS & dpi %in% c('d02','d04','d06','stock')) %>%
filter(type == 'index' | type == "stock") %>%
ggplot(., aes(x=segment, y = seg_deletion_richness, group = seg_weight, color = ferret_weight)) +
geom_boxplot(outlier.shape = NA) +
labs(x='segment',y='deletion richness') +
PlotTheme1 +
weight_colScale +
facet_grid(.~dpi)
print(p6)
ggsave(p6,
filename = glue("{wkdir}/DVG_figures/segment.index.richness.pdf"),
width = 8,
height = 4, limitsize=FALSE, useDingbats = FALSE)
ggsave(p6,
filename = glue("{wkdir}/DVG_figures/segment.index.richness.png"),
width =8,
height = 4, limitsize=FALSE) #, useDingbats = FALSE)

NA
NA
Test for significance
o = filter(seg_rich, type == "index" & dpi == "d02" & segment == "H9N2_PB2" & ferret_weight == "obese")
l = filter(seg_rich, type == "index" & dpi == "d02" & segment == "H9N2_PB2" & ferret_weight == "lean")
t.test(o$seg_deletion_richness,l$seg_deletion_richness)
Welch Two Sample t-test
data: o$seg_deletion_richness and l$seg_deletion_richness
t = -1.9934, df = 10.943, p-value = 0.07174
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-21.348926 1.063212
sample estimates:
mean of x mean of y
10.00000 20.14286
seg_rich %>% filter(type == 'index' & segment %in% SEGMENTS) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=type_day, y = seg_deletion_richness, color = segment, group=segment)) +
#geom_boxplot() +
geom_line(size = 1) +
geom_point(size = 2) +
labs(x='dpi (by index case)', y='DVG richness') +
PlotTheme1 +
scale_color_brewer(palette = 'Set2') +
#weight_colScale +
facet_grid(.~ferret_weight + ferret_id, scales = 'free', space = 'free')

p4 = seg_rich %>% filter(ferret_weight == 'obese' & index_direct == 'obese_obese' & segment %in% SEGMENTS) %>%
ungroup() %>%
unique() %>%
ggplot(., aes(x=type_day, y = seg_deletion_richness, color = segment, group=segment)) +
#geom_boxplot() +
geom_line(size = 1) +
geom_point(size = 2) +
labs(x='dpi (by index case)', y='DVG richness') +
PlotTheme1 +
scale_color_brewer(palette = 'Set2') +
#weight_colScale +
facet_grid(.~pair_ids, scales = 'free', space = 'free')
print(p4)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/segment.obese.to.obese.richness.pdf"),
width = 12,
height = 4, limitsize=FALSE, useDingbats = FALSE)
ggsave(p4,
filename = glue("{wkdir}/DVG_figures/segment.obese.to.obese.richness.png"),
width =12,
height = 4, limitsize=FALSE) #, useDingbats = FALSE)

End of Kate’s code
Which DVGs are shared between stock and index?
reps_df$DVG = paste0(reps_df$segment,"_",reps_df$DVG_group)
F17_stock = filter(reps_df ,type == "stock", cohort == "F17")
F17_stock_dvg = unique(F17_stock$DVG)
W17_stock = filter(reps_df ,type == "stock", cohort == "W17")
W17_stock_dvg = unique(W17_stock$DVG)
Sm18_stock = filter(reps_df ,type == "stock", cohort == "Sm18")
Sm18_stock_dvg = unique(Sm18_stock$DVG)
Sp19_stock = filter(reps_df ,type == "stock", cohort == "Sp19")
Sp19_stock_dvg = unique(Sp19_stock$DVG)
Sp20_stock = filter(reps_df ,type == "stock", cohort == "Sp20")
Sp20_stock_dvg = unique(Sp20_stock$DVG)
F17_index = filter(reps_df ,type == "index", cohort == "F17")
F17_index_dvg = unique(F17_index$DVG)
W17_index = filter(reps_df ,type == "index", cohort == "W17")
W17_index_dvg = unique(W17_index$DVG)
Sm18_index = filter(reps_df ,type == "index", cohort == "Sm18")
Sm18_index_dvg = unique(Sm18_index$DVG)
Sp19_index = filter(reps_df ,type == "index", cohort == "Sp19")
Sp19_index_dvg = unique(Sp19_index$DVG)
Sp20_index = filter(reps_df ,type == "index", cohort == "Sp20")
Sp20_index_dvg = unique(Sp20_index$DVG)
F17_shared = F17_index %>% filter(DVG %in% F17_stock_dvg) %>% filter((DVG %in% F17_index_dvg)) %>% unique()
F17_denovo = F17_index %>% filter((DVG %in% F17_index_dvg)) %>% filter(!(DVG %in% F17_stock_dvg)) %>% unique()
W17_shared = W17_index %>% filter(DVG %in% W17_stock_dvg) %>% filter((DVG %in% W17_index_dvg)) %>% unique()
W17_denovo = W17_index %>% filter((DVG %in% W17_index_dvg)) %>% filter(!(DVG %in% W17_stock_dvg)) %>% unique()
Sm18_shared = Sm18_index %>% filter(DVG %in% Sm18_stock_dvg) %>% filter((DVG %in% Sm18_index_dvg)) %>% unique()
Sm18_denovo = Sm18_index %>% filter((DVG %in% Sm18_index_dvg)) %>% filter(!(DVG %in% Sm18_stock_dvg)) %>% unique()
Sp19_shared = Sp19_index %>% filter(DVG %in% Sp19_stock_dvg) %>% filter((DVG %in% Sp19_index_dvg)) %>% unique()
Sp19_denovo = Sp19_index %>% filter((DVG %in% Sp19_index_dvg)) %>% filter(!(DVG %in% Sp19_stock_dvg)) %>% unique()
Sp20_shared = Sp20_index %>% filter(DVG %in% Sp20_stock_dvg) %>% filter((DVG %in% Sp20_index_dvg)) %>% unique() # still not working
Sp20_denovo = Sp20_index %>% filter((DVG %in% Sp20_index_dvg)) %>% filter(!(DVG %in% Sp20_stock_dvg)) %>% unique() # still not working
stock_shared = rbind(F17_shared,W17_shared,Sm18_shared,Sp19_shared,Sp20_shared)
index_unique = rbind(F17_denovo,W17_denovo,Sm18_denovo,Sp19_denovo,Sp20_denovo)
stock_obese = filter(stock_shared, ferret_weight == "obese")
o_dvg = unique(stock_obese$DVG)
stock_lean = filter(stock_shared, ferret_weight == "lean")
l_dvg = unique(stock_lean$DVG)
stock_dvg <- list(Obese = o_dvg, Lean = l_dvg)
StockDVGs = ggVennDiagram(stock_dvg)
print(StockDVGs)
ggsave(StockDVGs, file = "StockDVGs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

ShockSharedDVGs = ggplot(stock_shared, aes(x = dpi, y = DVG)) +
geom_point() +
geom_line(aes(group = DVG)) +
facet_grid(~segment) +
PlotTheme1
print(ShockSharedDVGs)
ggsave(ShockSharedDVGs, file = "ShockSharedDVGs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

Are there diet-specific DVGs in index ferrets?
index_obese = filter(index_unique, ferret_weight == "obese")
o_dvg = unique(index_obese$DVG)
index_lean = filter(index_unique, ferret_weight == "lean")
l_dvg = unique(index_lean$DVG)
diet_dvg <- list(Obese = o_dvg, Lean = l_dvg)
DietUniqueDVGs = ggVennDiagram(diet_dvg)
print(DietUniqueDVGs)
ggsave(DietUniqueDVGs, file = "DietUniqueDVGs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

Pulling out diet-specific DVGs
lean = index_lean %>%
filter(DVG %in% l_dvg) %>%
filter(!(DVG %in% o_dvg)) %>%
unique()
lean = lean %>%
group_by(DVG) %>%
mutate(count = 1, totalsamp = sum(count))
mult_lean = filter(lean, totalsamp > 1) %>%
unique()
obese = index_unique %>%
filter((DVG %in% o_dvg)) %>%
filter(!(DVG %in% l_dvg)) %>%
unique()
obese = obese %>%
group_by(DVG) %>%
mutate(count = 1, totalsamp = sum(count))
mult_obese = filter(obese, totalsamp > 1) %>%
unique()
lean_uniques = lean %>%
ungroup() %>%
select(segment,DVG_group,GroupBoundaries,totalsamp) %>%
unique() %>%
arrange(desc(totalsamp))
print(lean_uniques)
obese_uniques = obese %>%
ungroup() %>%
select(segment,DVG_group,GroupBoundaries,totalsamp) %>%
unique() %>%
arrange(desc(totalsamp))
print(obese_uniques)
Are DVGs transmitted?
dvg_df = select(reps_df, ferret_day, ferret_id, dpi, ferret_weight, type, segment, DVG_group, GroupBoundaries, pair, index_direct, pair_ids) %>%
ungroup() %>%
unique()
dvg_df$seg_dvg = paste0(dvg_df$segment,"_",dvg_df$DVG_group)
index = filter(dvg_df, type == "index") %>% unique()
first_time = c("1794_d04","1797_d02","1913_d06","1914_d06","1980_d02","1981_d10","1986_d10","2231_d06","2232_d02","2239_d02")
early_time = c("1794_d04","1797_d02","1980_d02","2232_d02","2239_d02")
direct = filter(dvg_df, ferret_day %in% first_time) %>% unique()
samples = unique(index$ferret_day)
dvg_transmitted = data.frame()
for(i in samples){
print(i)
n = filter(index, ferret_day == i)
partner = unique(n$pair_ids)
d = filter(direct, pair_ids %in% partner)
if(nrow(d) > 0){
s = unique(d$ferret_day)
print(s)
comp = merge(n, d, by = c("index_direct","pair_ids","pair","segment","seg_dvg","DVG_group","GroupBoundaries"), all.x = TRUE) %>%
count(pair_ids,ferret_day.x, ferret_day.y)
colnames(comp) = c("pair_ids","index","contact","count")
dvg_transmitted = rbind(dvg_transmitted, comp)
}else(print("No transmission"))
}
#dvg_transmitted = dvg_transmitted %>%
# pivot_wider(names_from = contact, values_from = count)
contact_dvgs = filter(dvg_df, type == "direct") %>% count(ferret_id,dpi,ferret_weight) %>%
ggplot(., aes(x = dpi, y = n, color = ferret_weight)) +
geom_point() +
geom_line(aes(group = ferret_id)) +
facet_grid(~ferret_id) +
ylab("DVG richness") +
xlab("DPI") +
PlotTheme1 +
weight_colScale
print(contact_dvgs)
ggsave(contact_dvgs, file = "contact_dvgs.pdf", path = saveitdir)
Saving 7.29 x 4.51 in image

LS0tCnRpdGxlOiAiRFZHX0FuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpLYXRlJ3MgRFZHIGNvZGUKCmBgYHtyfQptZXNzYWdlKCJMb2FkaW5nIHBhY2thZ2VzIikKbGlicmFyeSgnZ2dwbG90MicpCmxpYnJhcnkoJ3JlYWRyJykKbGlicmFyeSgncmVzaGFwZTInKQpsaWJyYXJ5KCdnZ3B1YnInKQpsaWJyYXJ5KCdwbHlyJykKbGlicmFyeSgndGlkeXZlcnNlJykKbGlicmFyeSgnZHBseXInKQpsaWJyYXJ5KCdnbHVlJykKbGlicmFyeSgnZ2dWZW5uRGlhZ3JhbScpCmBgYAoKYGBge3J9CiMgcGFyYW10ZXJzIHVzZWQgd2hlbiBydW5uaW5nIGRpdnJnZQpncm91cGluZ19wYXJhbSA9IDUKbWF0Y2hfbGVuZ3RoX3BhcmFtID0gMjgKcmVhZExlbmd0aCA9IDE1MAoKIyBkZWxldGlvbiByZWFkIGNvdW50IGN1dG9mZnMKY291bnRfY3V0ID0gMzAKCiMgb25seSBsb29raW5nIGF0IGluZGV4IGFuZCBkaXJlY3QgY2FzZXMKa2VlcGluZyA9IGMoJ2luZGV4JywnZGlyZWN0JykKYGBgCgpgYGB7cn0KbWVzc2FnZSgiU2V0dGluZyB3b3JrIGRpcmVjdG9yeSBhbmQgaW5wdXQgZmlsZSBuYW1lcyIpCndrZGlyID0gIi9Vc2Vycy9tYXJpc3Nha25vbGwvRGVza3RvcC9HaXRIdWIvT2Jlc2l0eS9OZXdFeHRyYWN0aW9ucy9IOU4yL0RWR3MiCnNldHdkKHdrZGlyKQpgYGAKCmBgYHtyfQppZiAoIWRpci5leGlzdHMoZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcyIpKSkgewogICAgICAgIGRpci5jcmVhdGUoZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcyIpKQogICAgICB9CgpzYXZlaXRkaXIgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzIikKYGBgCgpgYGB7cn0Kc291cmNlKGdsdWUoJ3t3a2Rpcn0vc2NyaXB0cy9vYmVzZV9QbG90UHJlcC5SJykpCmBgYAoKYGBge3J9CiMgbG9hZGluZyBpbiBtZXRhZGF0YSBhbmQgY292ZXJhZ2UgZGF0YQptZXRhZmlsZSA9IGdsdWUoInt3a2Rpcn0vc2NyaXB0cy90cmFuc21pc3Npb25faDluMl91c2VfbG9uZy5jc3YiKQptZXRhID0gcmVhZC5jc3YoZmlsZT1tZXRhZmlsZSxoZWFkZXI9VCxzZXA9IiwiLG5hLnN0cmluZ3MgPSBjKCcnKSkgCm1ldGEgPSBmaWx0ZXIobWV0YSwgZmxhZyA9PSAia2VlcCIpCmNvdmVyYWdlX3Bhc3NmaWxlID0gZ2x1ZSgne3drZGlyfS9zY3JpcHRzL0g5TjIuY292ZXJhZ2UucGFzcy5jaGVjay4yMDAuMC45NS5jc3YnKQpjb3ZfY2hlY2sgPSByZWFkLmNzdihmaWxlPWNvdmVyYWdlX3Bhc3NmaWxlLGhlYWRlcj1ULHNlcD0iLCIsbmEuc3RyaW5ncyA9IGMoJycpKQpgYGAKCmBgYHtyfQojIGZpbHRlciBmb3Igc2FtcGxlcyB0aGF0IGVpdGhlciBwYXNzIHdpdGggYSB5ZXMgT1IgaGFzIGdvb2QgYXZlcmFnZSBjb3ZlcmFnZSBhbmQgcGVyY2VudGFnZSBjb3YgYXQgMjAweCBpcyA+IDgwCmNvdl9maWx0X25hbWVzID0gY292X2NoZWNrICU+JSBmaWx0ZXIocGFzcyA9PSAnWUVTJyB8IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5fY292ZXJhZ2UgPj0gMjAwICB8IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2UgPiAwLjcpICU+JSAKICAgICAgICAgICAgc2VsZWN0KG5hbWUsIHNlZ21lbnQpICU+JSAKICAgICAgICAgICAgdW5pcXVlKCkKCmNvdl9maWx0X25hbWVzID0gZmlsdGVyKGNvdl9maWx0X25hbWVzLCBuYW1lICE9ICIyMjQ0X2QxMiIpICU+JSB1bmlxdWUoKQoKIyBjaGVjayBzZWdtZW50IGNvdW50CmNvdl9maWx0X25hbWVzID0gY292X2ZpbHRfbmFtZXMgJT4lIGdyb3VwX2J5KG5hbWUpICU+JSBhZGRfdGFsbHkobmFtZSA9ICdzZWdtZW50X3RhbGx5JykgJT4lIAogICAgICAgICAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHNlZ21lbnRfdGFsbHkgPT0gOCkgJT4lIAogICAgICAgICAgICAgICAgICAgIHVuaXF1ZSgpIAoKcHVsbF9uYW1lcyA9IGMobGV2ZWxzKGZhY3Rvcihjb3ZfZmlsdF9uYW1lcyRuYW1lKSkpICAjIGxpc3QgdG8gcHVsbCBuYW1lcyBmcm9tCmBgYAoKYGBge3J9CmR2Z2ZpbGUgPSBnbHVlKCd7d2tkaXJ9L0g5TjIuRFZHLkZJTkFMLk9uZUdhcC5ONS5NaXMyLk0yOC5HNS5jc3YnKSAjIGR2ZyBmaWxlCmR2ZyA9IHJlYWQuY3N2KGZpbGU9ZHZnZmlsZSxoZWFkZXI9VCxzZXA9IiwiLG5hLnN0cmluZ3MgPSBjKCcnKSkKCmR2ZyA9IGR2ZyAlPiUgZmlsdGVyKG5hbWUgJWluJSBwdWxsX25hbWVzKSAjIGZpbHRlciBmb3Igc2FtcGxlcyB0aGF0IHBhc3Mgb3VyIGNvdmVyYWdlIGNoZWNrcwpkdmckc2FtcGxlID0gZHZnJG5hbWUgICMgZ2VuZXJhdGUgbmV3IGNvbHVtbiBzbyB3ZSBjYW4gc2VwYXJhdGUKZHZnID0gZHZnICU+JSBzZXBhcmF0ZShzYW1wbGUsIGMoJ25ldycsJ2NvaG9ydCcsJ2ZlcnJldF9pZCcsJ2RwaScsJ3JlcCcpLCAnXycpICAjIHNlcGFyYXRlIGludG8gaW5mbwoKQ09OVFJPTFMgPSBkdmcgJT4lIGZpbHRlcihmZXJyZXRfaWQgPT0gJ0hLMTA3MycpICAjIHB1bGxpbmcgb3V0IGNvbnRyb2xzCkNPTlRST0xTJHJlcCA9IENPTlRST0xTJGRwaQpDT05UUk9MUyRkcGkgPSAnc3RvY2snICAjIGFkZGluZyBpbiBzdG9jayBpbmZvCgpkdmcgPSBkdmcgJT4lIGZpbHRlcighbmFtZSAlaW4lIGMobGV2ZWxzKGZhY3RvcihDT05UUk9MUyRuYW1lKSkpKSAlPiUgdW5pcXVlKCkKCmR2ZyA9IHJiaW5kKGR2ZywgQ09OVFJPTFMpICMgcmJpbmQgZXZlcnl0aGluZyBzbyBpdCBpcyBhbGwgaW4gb25lIGRhdGFmcmFtZQpgYGAKCmBgYHtyfQojIHByZXBwaW5nIHJlcCBpbmZvcm1hdGlvbgpkdmcgPSBkdmcgJT4lIHNlbGVjdCgtU2VnVG90YWxEVkcpICU+JSBmaWx0ZXIoRFZHX2ZyZXEgPj0gY291bnRfY3V0KSAlPiUgdW5pcXVlKCkgICMgZmlsdGVyIGZvciB0aG9zZSB0aGF0IHBhc3MgY3V0b2ZmcwpyZXAxID0gZHZnICU+JSBmaWx0ZXIocmVwID09ICdyZXAxJykgJT4lIHVuaXF1ZSgpCnJlcDIgPSBkdmcgJT4lIGZpbHRlcihyZXAgPT0gJ3JlcDInKSAlPiUgdW5pcXVlKCkKYGBgCgpgYGB7cn0KIyBtZXJnZSByZXBzIGludG8gb25lCmR2Z19yZXBzID0gbWVyZ2UocmVwMSwgcmVwMiwgYnkgPSBjKCdjb2hvcnQnLCdmZXJyZXRfaWQnLCdkcGknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzZWdtZW50Jywnc2VnbWVudF9zaXplJywnc3RyYWluJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnRFZHX2dyb3VwJywnTmV3R2FwJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTmV3U3RhcnQnLCdOZXdFbmQnLCdHcm91cEJvdW5kYXJpZXMnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdEZWxldGlvblNpemUnLCdFc3RpbWF0ZWRGcmFnTGVuZ3RoJyksIGFsbCA9IFRSVUUpICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQojIGFkZCBpbiB6ZXJvcwpkdmdfcmVwcyREVkdfZnJlcS54W2lzLm5hKGR2Z19yZXBzJERWR19mcmVxLngpXSA9IDAKZHZnX3JlcHMkRFZHX2ZyZXEueVtpcy5uYShkdmdfcmVwcyREVkdfZnJlcS55KV0gPSAwCmBgYAoKYGBge3J9CmdncGxvdChkdmdfcmVwcywgYWVzKHg9RFZHX2ZyZXEueCwgeT1EVkdfZnJlcS55KSkgKyAKICAgIGdlb21fcG9pbnQoKSArIAogICAgUGxvdFRoZW1lMQpgYGAKCmBgYHtyfQojIG51bWJlciBvZiBzYW1wbGVzPwpsZXZlbHMoZmFjdG9yKGR2Z19yZXBzJGZlcnJldF9pZCkpICU+JSBsZW5ndGgoKQpgYGAKCmBgYHtyfQojIHJlb3JkZXIgYnkgc2VnbWVudCBzaXplClNFR01FTlRTID0gYygnSDlOMl9QQjInLCAnSDlOMl9QQjEnLAogICAgICAgICAgICAnSDlOMl9QQScsJ0g5TjJfSEEnLCdIOU4yX05QJywgCiAgICAgICAgICAgICdIOU4yX05BJywnSDlOMl9NUCcsJ0g5TjJfTlMnKQoKY292X2NoZWNrJHNlZ21lbnQgPSBmYWN0b3IoY292X2NoZWNrJHNlZ21lbnQsIGxldmVscyA9IFNFR01FTlRTKQpgYGAKCmBgYHtyfQpjb3ZfY2hlY2sgJT4lIAogICAgZmlsdGVyKG5hbWUgJWluJSBwdWxsX25hbWVzKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD0gc2VnbWVudCwgeSA9IG1lYW5fY292ZXJhZ2UpKSArIAogICAgZ2VvbV9ib3hwbG90KCkgKyAKICAgIFBsb3RUaGVtZTEKCmNvdl9jaGVjayAlPiUgCiAgICBmaWx0ZXIobmFtZSAlaW4lIHB1bGxfbmFtZXMpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PSBzZWdtZW50LCB5ID0gbWVkaWFuX2NvdmVyYWdlKSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBQbG90VGhlbWUxCgpjb3ZfY2hlY2sgJT4lIAogICAgZmlsdGVyKG5hbWUgJWluJSBwdWxsX25hbWVzKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD0gc2VnbWVudCwgeSA9IHBlcmNlbnRhZ2UpKSArIAogICAgZ2VvbV9ib3hwbG90KCkgKyAKICAgIFBsb3RUaGVtZTEKYGBgCgpgYGB7cn0KZGYgPSBjb3ZfZmlsdF9uYW1lcyAlPiUgc2VsZWN0KC1zZWdtZW50LCAtc2VnbWVudF90YWxseSkgJT4lIHVuaXF1ZSgpCgpkZiRzYW1wbGUgPSBkZiRuYW1lCgpkZiA9IGRmICU+JSBzZXBhcmF0ZShzYW1wbGUsIGMoJ25ldycsJ2NvaG9ydCcsJ2ZlcnJldF9pZCcsJ2RwaScsJ3JlcCcpLCAnXycpCgpDT05UUk9MUyA9IGRmICU+JSBmaWx0ZXIoZmVycmV0X2lkID09ICdISzEwNzMnKQoKQ09OVFJPTFMkcmVwID0gQ09OVFJPTFMkZHBpCgpDT05UUk9MUyRkcGkgPSAnc3RvY2snCgoKZGYgPSBkZiAlPiUgZmlsdGVyKCFuYW1lICVpbiUgYyhsZXZlbHMoZmFjdG9yKENPTlRST0xTJG5hbWUpKSkpICU+JSB1bmlxdWUoKQoKZGYgPSByYmluZChkZiwgQ09OVFJPTFMpCgpyMSA9IGRmICU+JSBmaWx0ZXIocmVwID09ICdyZXAxJykgJT4lIHNlbGVjdCgtbmV3KSAlPiUgdW5pcXVlKCkKcjIgPSBkZiAlPiUgZmlsdGVyKHJlcCA9PSAncmVwMicpICU+JSBzZWxlY3QoLW5ldykgJT4lIHVuaXF1ZSgpCnJlcHMgPSBtZXJnZShyMSwgcjIsIGJ5ID0gYygnY29ob3J0JywnZmVycmV0X2lkJywnZHBpJykpICU+JSB1bmlxdWUoKQoKCiMgdGhlc2UgYXJlIHRoZSBzYW1wbGVzIHRoYXQgb25seSBoYWQgb25lIHJlcCEKc2V0ZGlmZihsZXZlbHMoZmFjdG9yKHIxJGZlcnJldF9pZCkpLAogICAgICAgbGV2ZWxzKGZhY3RvcihyMiRmZXJyZXRfaWQpKSkKYGBgCgpgYGB7cn0Kc2V0ZGlmZihtZXRhJGZlcnJldF9pZCwgcmVwcyRmZXJyZXRfaWQpICAjIHNhbXBsZXMgaW4gbWV0YSBub3QgaW4gc2VxIGRhdGEKc2V0ZGlmZihyZXBzJGZlcnJldF9pZCwgbWV0YSRmZXJyZXRfaWQpICMgc2FtcGxlcyBpbiBzZXEgZGF0YSBub3QgaW4gbWV0YQoKbSA9IG1lcmdlKHJlcHMsIG1ldGEsIGJ5ID0gYygnZmVycmV0X2lkJyksIGFsbCA9IFRSVUUpCgp3cml0ZS5jc3YobSwgZ2x1ZSgne3drZGlyfS9zY3JpcHRzL1VQREFURUQuSDlOMi5tZXRhZGF0YS5jc3YnKSwgcm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKYGBge3J9CnRlbXAgPSBtZXRhICU+JSAKICAgICAgICBmaWx0ZXIodHlwZSAlaW4lIGMoJ2luZGV4JywnZGlyZWN0JykpICU+JSAKICAgICAgICB1bmlxdWUoKSAlPiUgCiAgICAgICAgc2VsZWN0KHBhaXIsIHR5cGUsIGZlcnJldF9pZCkgJT4lIHVuaXF1ZSgpICU+JSAKICAgICAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gJ3R5cGUnLCB2YWx1ZXNfZnJvbSA9ICdmZXJyZXRfaWQnKQoKdGVtcCA9IHJiaW5kKHRlbXAsIGMoJ1onLCdzdG9jaycsJ3N0b2NrJykpCgp0ZW1wJHBhaXJfaWRzID0gcGFzdGUwKHRlbXAkaW5kZXgsJz4nLHRlbXAkZGlyZWN0KQoKdGVtcCA9IHRlbXAgICU+JSBzZWxlY3QocGFpciwgcGFpcl9pZHMpICU+JSB1bmlxdWUoKQoKbSA9IG1lcmdlKG0sIHRlbXAsIGJ5ID0gYygncGFpcicpKSAgIyBhZGQgaW4gYWRkaXRpb25hbCBpbmZvcm1hdGlvbiB0byBtZXRhZGF0YSB0byB3b3JrIHdpdGgKYGBgCgpgYGB7cn0KIyB0eXBlIGNoZWNrIC0gb25seSBzdG9jayBpbmRleCBkaXJlY3QKcHJpbnQobGV2ZWxzKGZhY3RvcihtJHR5cGUpKSkKYGBgCgpgYGB7cn0KbSR0eXBlID0gZmFjdG9yKG0kdHlwZSwgbGV2ZWxzID0gYygnc3RvY2snLCdpbmRleCcsJ2RpcmVjdCcpKQoKbSA9IG0gJT4lIGZpbHRlcihuYW1lLnggIT0gaXMubmEobmFtZS54KSkgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CnAxID0gbSAlPiUgZmlsdGVyKGZlcnJldF9pZCAhPSAnSEsxMDczJykgJT4lIHVuaXF1ZSgpICU+JSAKICAgIGdncGxvdCguLCBhZXMoeD0gZHBpLCB5ID0gcGFpcl9pZHMsIGZpbGwgPSBmZXJyZXRfd2VpZ2h0KSkgKyAKICAgIGdlb21fdGlsZShjb2xvciA9ICdibGFjaycpICsgCiAgICBQbG90VGhlbWUzICsKICAgIHdlaWdodF9jb2xGaWxsICsgCiAgICBmYWNldF9ncmlkKGluZGV4X2RpcmVjdH50eXBlLCBzY2FsZXMgPSAnZnJlZScsIHNwYWNlID0gJ2ZyZWUnKQoKcHJpbnQocDEpCgpnZ3NhdmUocDEsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvZmluYWwuc2FtcGxlcy5wZGYiKSwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIGhlaWdodCA9IDYsIGxpbWl0c2l6ZT1GQUxTRSwgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCmdnc2F2ZShwMSwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9maW5hbC5zYW1wbGVzLnBuZyIpLAogICAgICAgd2lkdGggPSA2LAogICAgICAgaGVpZ2h0ID0gNiwgbGltaXRzaXplPUZBTFNFKSAjLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQpgYGAKCmBgYHtyfQpkdmdfcmVwcyA9IGR2Z19yZXBzICU+JSAKICAgICAgICAgICAgZmlsdGVyKERWR19mcmVxLnggPiBjb3VudF9jdXQgJiBEVkdfZnJlcS55ID4gY291bnRfY3V0KSAlPiUgCiAgICAgICAgdW5pcXVlKCkgICAjIG1ha2Ugc3VyZSB0aGF0IGJvdGggcmVwcyBwYXNzIG91ciBjdXRvZmYKCiMgYWRkIGluIHZhcmlhYmxlcyBmb3IgcGxvdHRpbmcKZHZnX3JlcHMkZmVycmV0X2RheSA9IHBhc3RlMChkdmdfcmVwcyRmZXJyZXRfaWQsICdfJywgZHZnX3JlcHMkZHBpKSAgCgptJGZlcnJldF9kYXkgPSBwYXN0ZTAobSRmZXJyZXRfaWQsICdfJywgbSRkcGkpCmBgYAoKYGBge3J9CnN0b2NrX3RlbXAgPSBkdmdfcmVwcyAlPiUgZmlsdGVyKGRwaSA9PSAnc3RvY2snKSAlPiUKICAgIGdyb3VwX2J5KGZlcnJldF9pZCwgY29ob3J0LCBkcGksIHNlZ21lbnQsIG5hbWUueCwgbmFtZS55KSAlPiUKICAgIGFkZF90YWxseShuYW1lID0gJ3NlZ19kZWxldGlvbl9yaWNobmVzcycpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICB1bmdyb3VwKCkgJT4lIAogICAgZ3JvdXBfYnkoZmVycmV0X2lkLCBkcGksIG5hbWUueCwgbmFtZS55LCBjb2hvcnQpICU+JSAKICAgIGFkZF90YWxseShuYW1lID0gJ2RlbGV0aW9uX3JpY2huZXNzJykgJT4lCiAgICB1bmdyb3VwKCkgJT4lIAogICAgdW5pcXVlKCkKCnMgPSBzdG9ja190ZW1wICAjIHdpbGwgdXNlIGxhdGVyCgojIGZpbHRlciBkb3duIHN0b2NrIHRlbXAgaW5mb3JtYXRpb24Kc3RvY2tfdGVtcCA9IHN0b2NrX3RlbXAgJT4lIAogICAgICAgICAgICBzZWxlY3QoZmVycmV0X2lkLCBkcGksIGNvaG9ydCxmZXJyZXRfZGF5LCBzZWdtZW50LCBkZWxldGlvbl9yaWNobmVzcywgc2VnX2RlbGV0aW9uX3JpY2huZXNzKSAlPiUKICAgICAgICAgICAgdW5pcXVlKCkKCgpzdG9ja190ZW1wID0gbWVyZ2Uoc3RvY2tfdGVtcCwgbSwgYnkgPSBjKCdmZXJyZXRfaWQnLCAnZHBpJywnY29ob3J0JywnZmVycmV0X2RheScpKSAlPiUgCiAgICB1bmlxdWUoKQpgYGAKCmBgYHtyfQojIGZpbHRlciBvdXQgc3RvY2sgaW5mb3JtYXRpb24sIGNhbGN1bGF0ZSBkdmcgcmljaG5lc3MgYnkgc2VnbWVudCBhbmQgYWNyb3NzIGdlbm9tZSBmb3Igc2FtcGxlcwoKZHIgPSBkdmdfcmVwcyAlPiUgCiAgICAgICAgICAgIGZpbHRlcihkcGkgIT0gJ3N0b2NrJykgJT4lIAogICAgICAgICAgICB1bmlxdWUoKSAlPiUgCiAgICAgICAgICAgIGdyb3VwX2J5KGZlcnJldF9pZCwgZHBpLCBzZWdtZW50LCBuYW1lLngsIG5hbWUueSwgY29ob3J0KSAlPiUKICAgICAgICAgICAgYWRkX3RhbGx5KG5hbWUgPSAnc2VnX2RlbGV0aW9uX3JpY2huZXNzJykgJT4lCiAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUgCiAgICAgICAgICAgIGdyb3VwX2J5KGZlcnJldF9pZCwgZHBpLCBuYW1lLngsIG5hbWUueSwgY29ob3J0KSAlPiUgCiAgICAgICAgICAgIGFkZF90YWxseShuYW1lID0gJ2RlbGV0aW9uX3JpY2huZXNzJykgJT4lCiAgICAgICAgICAgIHVuZ3JvdXAoKSAlPiUgCiAgICAgICAgICAgIHVuaXF1ZSgpCgojIGZpbHRlciBkb3duIGluZm9ybWF0aW9uIHNvIHlvdSBkb24ndCBoYXZlIGR1cGxpY2F0ZXMKcmljaG5lc3MgPSBkciAlPiUgCiAgICAgICAgICAgIHNlbGVjdChmZXJyZXRfaWQsIGRwaSwgY29ob3J0LGZlcnJldF9kYXksIHNlZ21lbnQsIGRlbGV0aW9uX3JpY2huZXNzLCBzZWdfZGVsZXRpb25fcmljaG5lc3MpICU+JQogICAgICAgICAgICB1bmlxdWUoKQoKIyBtZXJnZSB3aXRoIG1ldGFkYXRhIGluZm8KcmljaG5lc3MgPSBtZXJnZShyaWNobmVzcywgbSwgYnkgPSBjKCdmZXJyZXRfaWQnLCAnZHBpJywnY29ob3J0JywnZmVycmV0X2RheScpLCBhbGwueSA9IFRSVUUpICU+JQogICAgdW5pcXVlKCkKCiMgbWFrZSBzdXJlIHdlIGZpbHRlciBvdXQgc3RvY2sgaW5mb3JtYXRpb24gKHdpbGwgYWRkIHVzaW5nIHRoZSAncycgZGF0YWZyYW1lIGdlbmVyYXRlZCBhYm92ZSkKcmljaG5lc3MgPSByaWNobmVzcyAlPiUgZmlsdGVyKGRwaSAhPSAnc3RvY2snKQoKcmVwc19kZiA9IHJiaW5kKGRyLCBzKSAjIGZpbmFsIHJlcHMgcmljaG5lc3MgZGYKCnJlcHNfZGYgPSBtZXJnZShyZXBzX2RmLCBtLCBieSA9IGMoJ2ZlcnJldF9pZCcsJ2RwaScsJ2NvaG9ydCcsJ2ZlcnJldF9kYXknKSkgICMgYWRkIG1ldGFkYXRhCmBgYAoKYGBge3J9CnA0ID0gcmVwc19kZiAlPiUgCiAgICBzZWxlY3Qoc2VnbWVudCwgTmV3R2FwLCBFc3RpbWF0ZWRGcmFnTGVuZ3RoLCBmZXJyZXRfd2VpZ2h0KSAlPiUKICAgIHVuaXF1ZSgpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PSBFc3RpbWF0ZWRGcmFnTGVuZ3RoKSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGNvbG9yID0gJ2JsYWNrJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgbGFicyh4PSJlc3RpbWF0ZWQgRFZHIGZyYWcuIGxlbmd0aCAobnQpIiwgeT0nbnVtYmVyIG9mIHVuaXF1ZSBEVkcgc3BlY2llcycpIApwcmludChwNCkKCmdnc2F2ZShwNCwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9kZWxldGlvbi5zaXplLnBkZiIpLAogICAgICAgd2lkdGggPSA1LAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHA0LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL2RlbGV0aW9uLnNpemUucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCnA0X2FsdCA9IHJlcHNfZGYgJT4lIAogICAgc2VsZWN0KHNlZ21lbnQsIE5ld0dhcCwgRXN0aW1hdGVkRnJhZ0xlbmd0aCwgZmVycmV0X3dlaWdodCwgdHlwZSkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD0gRXN0aW1hdGVkRnJhZ0xlbmd0aCkpICsgCiAgICBnZW9tX2hpc3RvZ3JhbShjb2xvciA9ICdibGFjaycsIGJpbndpZHRoID0gNTApICsgCiAgICBmYWNldF9ncmlkKHR5cGV+ZmVycmV0X3dlaWdodCkgKwogICAgUGxvdFRoZW1lMSArCiAgICBsYWJzKHg9ImVzdGltYXRlZCBEVkcgZnJhZy4gbGVuZ3RoIChudCkiLCB5PSdudW1iZXIgb2YgdW5pcXVlIERWRyBzcGVjaWVzJykgCnByaW50KHA0X2FsdCkKZ2dzYXZlKHA0X2FsdCwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9kZWxldGlvbi5zaXplLmJ5ZGlldC5ieXR5cGUucGRmIiksCiAgICAgICB3aWR0aCA9IDEwLAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKYGBgCgpgYGB7cn0KbGVhbl9pbmRleCA9ICByZXBzX2RmICU+JSBmaWx0ZXIodHlwZSA9PSAnaW5kZXgnICYgZmVycmV0X3dlaWdodCA9PSAnbGVhbicpICU+JSAKICAgICAgICAgICAgICAgIHVuaXF1ZSgpICU+JQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoTmV3R2FwLCBzZWdtZW50LCBOZXdTdGFydCwgTmV3RW5kKSAlPiUKICAgICAgICAgICAgYWRkX3RhbGx5KG5hbWUgPSAnbGVhbl9kZWxldGlvbl9jb3VudCcpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgc2VsZWN0KE5ld0dhcCwgc2VnbWVudCwgbGVhbl9kZWxldGlvbl9jb3VudCkgJT4lCiAgICB1bmlxdWUoKQoKCm9iZXNlX2luZGV4ID0gIHJlcHNfZGYgJT4lIGZpbHRlcih0eXBlID09ICdpbmRleCcgJiBmZXJyZXRfd2VpZ2h0ID09ICdvYmVzZScpICU+JSAKICAgICAgICAgICAgICAgIHVuaXF1ZSgpICU+JQogICAgICAgICAgICAgICAgZ3JvdXBfYnkoTmV3R2FwLCBzZWdtZW50LCBOZXdTdGFydCwgTmV3RW5kKSAlPiUKICAgICAgICAgICAgYWRkX3RhbGx5KG5hbWUgPSAnb2Jlc2VfZGVsZXRpb25fY291bnQnKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHNlbGVjdChOZXdHYXAsIHNlZ21lbnQsIG9iZXNlX2RlbGV0aW9uX2NvdW50KSAlPiUKICAgIHVuaXF1ZSgpCgoKZGYgPSBtZXJnZShsZWFuX2luZGV4LCBvYmVzZV9pbmRleCwgYnkgPSBjKCdOZXdHYXAnLCdzZWdtZW50JyksIGFsbCA9IFRSVUUpIAoKaGVhZChkZikKCmRmJGxlYW5fZGVsZXRpb25fY291bnRbaXMubmEoZGYkbGVhbl9kZWxldGlvbl9jb3VudCldID0gMAoKZGYkb2Jlc2VfZGVsZXRpb25fY291bnRbaXMubmEoZGYkb2Jlc2VfZGVsZXRpb25fY291bnQpXSA9IDAKYGBgCgpgYGB7cn0KcDggPSByZXBzX2RmICU+JSBmaWx0ZXIodHlwZSA9PSAnaW5kZXgnKSAlPiUgCiAgICAgICAgICAgICAgICB1bmlxdWUoKSAlPiUKICAgICAgICAgICAgICAgIGdyb3VwX2J5KE5ld0dhcCwgc2VnbWVudCwgTmV3U3RhcnQsIE5ld0VuZCkgJT4lCiAgICAgICAgICAgIGFkZF90YWxseShuYW1lID0gJ3NhbXBsZV9jb3VudCcpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgc2VsZWN0KE5ld0dhcCwgc2VnbWVudCxzYW1wbGVfY291bnQpICU+JQogICAgdW5pcXVlKCkgICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PXNhbXBsZV9jb3VudCwgeSA9IC4uY291bnQuLi9zdW0oLi5jb3VudC4uKSkpICsKICAgIGdlb21faGlzdG9ncmFtKGNvbG9yID0nYmxhY2snKSArIAogICAgbGFicyh4PSdudW1iZXIgb2Ygc2FtcGxlcyB3aXRoIERWRyB0eXBlJywgeT0ncHJvcG9ydGlvbiBvZiBEVkdzIGluIGRhdGFzZXQgKGluZGV4IG9ubHkpJykgKyAKICAgIFBsb3RUaGVtZTEgCgpwcmludChwOCkKZ2dzYXZlKHA4LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NhbXBsZS5jb3VudC5oaXN0by5wZGYiKSwKICAgICAgIHdpZHRoID0gNSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSwgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCmdnc2F2ZShwOCwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zYW1wbGUuY291bnQuaGlzdG8ucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgpgYGB7cn0KcmVwc19kZiRhdmVfZHZnX2ZyZXEgPSAocmVwc19kZiREVkdfZnJlcS54ICsgcmVwc19kZiREVkdfZnJlcS55KS8yCmBgYAoKYGBge3J9CnJlcHNfZGYgPSByZXBzX2RmICU+JQogIGFycmFuZ2UoZmVycmV0X2RheSwgYXZlX2R2Z19mcmVxKSAlPiUgCiAgZ3JvdXBfYnkoZmVycmV0X2RheSkgJT4lIAogIG11dGF0ZShvcmRlcl9udW1iZXIgPSByb3dfbnVtYmVyKCkpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgdW5pcXVlKCkKYGBgCgpgYGB7cn0KcmVwc19kZiAlPiUgCiAgICBncm91cF9ieShOZXdHYXAsIHNlZ21lbnQsIHR5cGUsIGZlcnJldF93ZWlnaHQpICU+JQogICAgbXV0YXRlKG1lYW5fb3JkZXIgPSBtZWFuKG9yZGVyX251bWJlciksCiAgICAgICAgICBzYW1wbGVfY291bnQgPSBuKCksCiAgICAgICAgICBtaW5fb3JkZXIgPSBtaW4ob3JkZXJfbnVtYmVyKSwKICAgICAgICAgIG1heF9vcmRlciA9IG1heChvcmRlcl9udW1iZXIpLAogICAgICAgICAgbWVkaWFuX29yZCA9IG1lZGlhbihvcmRlcl9udW1iZXIpKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHVuaXF1ZSgpICU+JQogICAgc2VsZWN0KHNlZ21lbnQsIE5ld0dhcCwgbWVhbl9vcmRlciwgc2FtcGxlX2NvdW50LCBtaW5fb3JkZXIsIG1heF9vcmRlciwgbWVkaWFuX29yZCwgdHlwZSwgZmVycmV0X3dlaWdodCkgJT4lCiAgICBmaWx0ZXIoc2FtcGxlX2NvdW50ID4gMSkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeT1tZWFuX29yZGVyLCB4ID0gc2FtcGxlX2NvdW50KSkgKyAKICAgIGdlb21fcG9pbnQoKSArIAogICAgUGxvdFRoZW1lMSArIAogICAgZmFjZXRfZ3JpZCgufmZlcnJldF93ZWlnaHQgKyB0eXBlKQpgYGAKCmBgYHtyfQp0b3BfdGVuID0gcmVwc19kZiAlPiUgZmlsdGVyKG9yZGVyX251bWJlciAlaW4lIGMoMSwgMiwzICw0LCA1LCA2LCA3LCA4LCA5LCAxMCkpICU+JSB1bmlxdWUoKQoKaGVhZCh0b3BfdGVuKQoKbGVuZ3RoKGxldmVscyhmYWN0b3IodG9wX3RlbiROZXdHYXApKSkKYGBgCgpgYGB7cn0KbWF4KGRmJGxlYW5fZGVsZXRpb25fY291bnQpCm1heChkZiRvYmVzZV9kZWxldGlvbl9jb3VudCkKCnA5ID0gZ2dwbG90KGRmLCBhZXMoeD1sZWFuX2RlbGV0aW9uX2NvdW50LCB5ID0gb2Jlc2VfZGVsZXRpb25fY291bnQpKSArIAogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjEsIGhlaWdodCA9IDAuMSwgYWxwaGEgPSAwLjMpICsgCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gJ2JsYWNrJykgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMjUsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAncmVkJykgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICdibGFjaycpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDE3LCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gJ3JlZCcpICsKICAgIGxhYnMoeD0gJ251bWJlciBvZiBsZWFuIHNhbXBsZXMgd2l0aCBEVkcnLCB5PSdudW1iZXIgb2Ygb2Jlc2Ugc2FtcGxlcyB3aXRoIERWRycpICsgCiAgICBQbG90VGhlbWUxIAoKcHJpbnQocDkpCmdnc2F2ZShwOSwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zYW1wbGUuY291bnQubGVhbi52Lm9iZXNlLnBkZiIpLAogICAgICAgd2lkdGggPSA1LAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHA5LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NhbXBsZS5jb3VudC5sZWFuLnYub2Jlc2UucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgpgYGB7cn0KcmVwc19kZiAlPiUgZmlsdGVyKHR5cGUgPT0gJ2luZGV4JyAmIGZlcnJldF93ZWlnaHQgPT0gJ29iZXNlJykgJT4lIHNlbGVjdChuYW1lLngueCkgJT4lIHVuaXF1ZSgpICU+JSBucm93KCkKcmVwc19kZiAlPiUgZmlsdGVyKHR5cGUgPT0gJ2luZGV4JyAmIGZlcnJldF93ZWlnaHQgPT0gJ2xlYW4nKSAlPiUgc2VsZWN0KG5hbWUueC54KSAlPiUgdW5pcXVlKCkgJT4lIG5yb3coKQpgYGAKCmBgYHtyfQpyaWNobmVzcyA9IHJiaW5kKHJpY2huZXNzLCBzdG9ja190ZW1wKQpyaWNobmVzcyRkZWxldGlvbl9yaWNobmVzc1tpcy5uYShyaWNobmVzcyRkZWxldGlvbl9yaWNobmVzcyldID0gMApEQVlTID0gYygnc3RvY2snLCdkMDInLCdkMDQnLCdkMDYnLCdkMDgnLCdkMTAnLCdkMTInKQpgYGAKCmBgYHtyfQpyaWNobmVzcyRjb2hvcnQgPSBnc3ViKCJGQ0MiLCJTcDE5IixyaWNobmVzcyRjb2hvcnQpCnJpY2huZXNzJGRwaSA9IGZhY3RvcihyaWNobmVzcyRkcGksIGxldmVscyA9IERBWVMpCnJpY2huZXNzICU+JSBmaWx0ZXIoZHBpICVpbiUgYygnZDAyJywnZDA0JykpICU+JQogICAgICAgIGZpbHRlcih0eXBlID09ICdpbmRleCcgfCB0eXBlID09ICdzdG9jaycpICU+JQogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBkZWxldGlvbl9yaWNobmVzcywgdHlwZSwgZmVycmV0X3dlaWdodCwgaW5kZXhfZGlyZWN0LCBjb2hvcnQpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBncm91cF9ieShmZXJyZXRfaWQpICU+JQogICAgYWRkX3RhbGx5KG5hbWUgPSAnbicpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZmlsdGVyKG4gPj0gMikgJT4lIAogICAgdW5ncm91cCgpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9ZHBpLCB5ID0gZGVsZXRpb25fcmljaG5lc3MsIGNvbG9yID0gY29ob3J0LCBncm91cD1mZXJyZXRfaWQsIHNoYXBlID0gZmVycmV0X3dlaWdodCkpICsgCiAgICAjZ2VvbV9ib3hwbG90KCkgKyAKICAgIGdlb21fbGluZSgpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAogICAgUGxvdFRoZW1lMSArCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICdTZXQxJykKICAgICN3ZWlnaHRfY29sU2NhbGUgKyAKICAgICNmYWNldF9ncmlkKC5+Y29ob3J0KQoKCnA3ID0gcmljaG5lc3MgJT4lIGZpbHRlcihkcGkgJWluJSBjKCdkMDInLCdkMDQnLCdkMDYnKSkgJT4lCiAgICAgICAgZmlsdGVyKHR5cGUgPT0gJ2luZGV4JyB8IHR5cGUgPT0gJ3N0b2NrJykgJT4lICAgIAogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBkZWxldGlvbl9yaWNobmVzcywgdHlwZSwgZmVycmV0X3dlaWdodCwgaW5kZXhfZGlyZWN0LCBjb2hvcnQpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBncm91cF9ieShmZXJyZXRfaWQpICU+JQogICAgYWRkX3RhbGx5KG5hbWUgPSAnbicpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZmlsdGVyKG4gPj0gMikgJT4lIAogICAgdW5ncm91cCgpICU+JQogICAgdW5pcXVlKCkgJT4lCiAgICBnZ3Bsb3QoLiwgYWVzKHg9ZHBpLCB5ID0gZGVsZXRpb25fcmljaG5lc3MsIGNvbG9yID0gZmVycmV0X3dlaWdodCwgZ3JvdXA9ZmVycmV0X2lkLCBzaGFwZSA9IGZlcnJldF93ZWlnaHQpKSArIAogICAgI2dlb21fYm94cGxvdCgpICsgCiAgICBnZW9tX2xpbmUoKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgd2VpZ2h0X2NvbFNjYWxlCiAgICAjZmFjZXRfZ3JpZCgufmNvaG9ydCkKCnByaW50KHA3KQpnZ3NhdmUocDcsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvcmljaG5lc3MuaW5kZXgucGRmIiksCiAgICAgICB3aWR0aCA9IDUsCiAgICAgICBoZWlnaHQgPSA1LCBsaW1pdHNpemU9RkFMU0UsIHVzZURpbmdiYXRzID0gRkFMU0UpCgpnZ3NhdmUocDcsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvcmljaG5lc3MuaW5kZXgucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgpgYGB7cn0KY29sbmFtZXMocmljaG5lc3MpCm9yZGVyX3R5cGVkYXkgPSBjKCdzdG9jaycsJ2luZGV4X2QwMicsJ2luZGV4X2QwNCcsCiAgICAgICAgICAgICAgICAgJ2luZGV4X2QwNicsJ2luZGV4X2QwOCcsJ2luZGV4X2QxMCcsCiAgICAgICAgICAgICAgICAgJ2luZGV4X2QxMicsCiAgICAgICAgICAgICAgICAgJ2RpcmVjdF9kMDInLCdkaXJlY3RfZDA0JywKICAgICAgICAgICAgICAgICAnZGlyZWN0X2QwNicsJ2RpcmVjdF9kMDgnLCdkaXJlY3RfZDEwJywKICAgICAgICAgICAgICAgICAnZGlyZWN0X2QxMicpCmBgYAoKYGBge3J9CnJpY2huZXNzJHR5cGVfZGF5ID0gcGFzdGUwKHJpY2huZXNzJHR5cGUsICdfJywgcmljaG5lc3MkZHBpKQpyaWNobmVzcyR0eXBlX2RheSA9IGZhY3RvcihyaWNobmVzcyR0eXBlX2RheSwgbGV2ZWxzID0gb3JkZXJfdHlwZWRheSkKCnAyID0gcmljaG5lc3MgJT4lIGZpbHRlcihmZXJyZXRfd2VpZ2h0ID09ICdvYmVzZScgJiBpbmRleF9kaXJlY3QgPT0gJ29iZXNlX29iZXNlJykgJT4lCiAgICBzZWxlY3QoZmVycmV0X2lkLCBkcGksIGRlbGV0aW9uX3JpY2huZXNzLCB0eXBlLCBmZXJyZXRfd2VpZ2h0LCAKICAgICAgICAgICBwYWlyX2lkcywgaW5kZXhfZGlyZWN0LCB0eXBlX2RheSkgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD10eXBlX2RheSwgeSA9IGRlbGV0aW9uX3JpY2huZXNzLCBjb2xvciA9IHBhaXJfaWRzLCBncm91cD1wYWlyX2lkcykpICsgCiAgICAjZ2VvbV9ib3hwbG90KCkgKyAKICAgIGdlb21fbGluZShzaXplID0gMSkgKyAKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgCiAgICBsYWJzKHg9J2RwaSAoYnkgaW5kZXggY2FzZSknLCB5PSdEVkcgcmljaG5lc3MnKSArIAogICAgUGxvdFRoZW1lMSArCiAgICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICdTZXQyJykgIysKICAgICN3ZWlnaHRfY29sU2NhbGUgKyAKICAgICNmYWNldF9ncmlkKC5+dHlwZSkKCnByaW50KHAyKQpnZ3NhdmUocDIsCiAgICAgICBmaWxlbmFtZSA9IGdsdWUoInt3a2Rpcn0vRFZHX2ZpZ3VyZXMvb2Jlc2UudG8ub2Jlc2UuZGl2ZXJzaXR5LnBkZiIpLAogICAgICAgd2lkdGggPSA4LAogICAgICAgaGVpZ2h0ID0gNiwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHAyLAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL29iZXNlLnRvLm9iZXNlLmRpdmVyc2l0eS5wbmciKSwKICAgICAgIHdpZHRoID04LAogICAgICAgaGVpZ2h0ID0gNiwgbGltaXRzaXplPUZBTFNFKSAjLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQpgYGAKCmBgYHtyfQpnZW5fcmljaCA9IHJpY2huZXNzICU+JSAKICBzZWxlY3QoZmVycmV0X2lkLCBkcGksIGNvaG9ydCxkZWxldGlvbl9yaWNobmVzcywgdHlwZSwgZmVycmV0X3dlaWdodCwgcGFpcl9pZHMsIGluZGV4X2RpcmVjdCwgdHlwZV9kYXkpICU+JQogIHVuaXF1ZSgpCgpoZWFkKGdlbl9yaWNoKQoKZ2VuX3JpY2ggJT4lIGZpbHRlcihkcGkgJWluJSBjKCdkMDInLCdkMDQnLCdkMDYnLCdzdG9jaycpKSAlPiUKICAgIGZpbHRlcih0eXBlID09ICdpbmRleCcgfCB0eXBlID09ICJzdG9jayIpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PWZlcnJldF93ZWlnaHQsIHkgPSBkZWxldGlvbl9yaWNobmVzcywgZ3JvdXAgPSBmZXJyZXRfd2VpZ2h0KSkgKyAKICAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsgCiAgICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgYWVzKGNvbG9yID0gZmVycmV0X3dlaWdodCkpICsKICAgIGxhYnMoeD0nc2VnbWVudCcseT0nZGVsZXRpb24gcmljaG5lc3MnKSArIAogICAgUGxvdFRoZW1lMSArCiAgICB3ZWlnaHRfY29sU2NhbGUgKwogICAgZmFjZXRfZ3JpZCgufmRwaSkKYGBgCgpUZXN0IGZvciBzaWduaWZpY2FuY2UKYGBge3J9Cm8gPSBmaWx0ZXIoZ2VuX3JpY2gsIHR5cGUgPT0gImluZGV4IiAmIGRwaSA9PSAiZDA2IiAmIGZlcnJldF93ZWlnaHQgPT0gIm9iZXNlIikKbCA9IGZpbHRlcihnZW5fcmljaCwgdHlwZSA9PSAiaW5kZXgiICYgZHBpID09ICJkMDYiICYgZmVycmV0X3dlaWdodCA9PSAibGVhbiIpCnQudGVzdChvJGRlbGV0aW9uX3JpY2huZXNzLGwkZGVsZXRpb25fcmljaG5lc3MpCmBgYAoKYGBge3J9CnNlZ19yaWNoID0gcmljaG5lc3MgJT4lICNmaWx0ZXIoZmVycmV0X3dlaWdodCA9PSAnb2Jlc2UnICYgaW5kZXhfZGlyZWN0ID09ICdvYmVzZV9vYmVzZScpICU+JQogICAgc2VsZWN0KGZlcnJldF9pZCwgZHBpLCBzZWdfZGVsZXRpb25fcmljaG5lc3MsIHR5cGUsIGZlcnJldF93ZWlnaHQsIAogICAgICAgICAgIHBhaXJfaWRzLCBpbmRleF9kaXJlY3QsIHR5cGVfZGF5LCBzZWdtZW50KSAlPiUKICAgIHVuaXF1ZSgpCgpoZWFkKHNlZ19yaWNoKQoKdGVtcCA9IHNlZ19yaWNoICU+JSBzZWxlY3QoZmVycmV0X2lkLCBkcGksIHR5cGUsIGZlcnJldF93ZWlnaHQsIHBhaXJfaWRzLCB0eXBlX2RheSwgaW5kZXhfZGlyZWN0KSAlPiUgdW5pcXVlKCkKdGVtcCRIOU4yX1BCMiA9IDAKdGVtcCRIOU4yX1BCMSA9IDAKdGVtcCRIOU4yX1BBID0gMAp0ZW1wJEg5TjJfSEEgPSAwCnRlbXAkSDlOMl9OUCA9IDAKdGVtcCRIOU4yX05BID0gMAp0ZW1wJEg5TjJfTVAgPSAwCnRlbXAkSDlOMl9OUyA9IDAKCnRlbXAgPSBwaXZvdF9sb25nZXIodGVtcCwgY29scyA9IGFsbF9vZihTRUdNRU5UUyksIG5hbWVzX3RvID0gJ3NlZ21lbnQnKSAlPiUgc2VsZWN0KC12YWx1ZSkKCnNlZ19yaWNoID0gbWVyZ2Uoc2VnX3JpY2gsIHRlbXAsIGJ5ID0gYygnZmVycmV0X2lkJywgJ2RwaScsICd0eXBlJywgJ2ZlcnJldF93ZWlnaHQnLCAKICAgICAgICAgICAncGFpcl9pZHMnLCAnaW5kZXhfZGlyZWN0JywgJ3R5cGVfZGF5JywgJ3NlZ21lbnQnKSwgYWxsID0gVFJVRSkgCgpzZWdfcmljaCRzZWdfZGVsZXRpb25fcmljaG5lc3NbaXMubmEoc2VnX3JpY2gkc2VnX2RlbGV0aW9uX3JpY2huZXNzKV0gPSAwCgpzZWdfcmljaCRzZWdtZW50ID0gZmFjdG9yKHNlZ19yaWNoJHNlZ21lbnQsIGxldmVscyA9IFNFR01FTlRTKQpoZWFkKHNlZ19yaWNoKQpgYGAKCmBgYHtyfQpwMyA9IHNlZ19yaWNoICU+JSBmaWx0ZXIoc2VnbWVudCAlaW4lIFNFR01FTlRTKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD1zZWdtZW50LCB5ID0gc2VnX2RlbGV0aW9uX3JpY2huZXNzKSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgCgpwcmludChwMykKCmdnc2F2ZShwMywKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zZWdtZW50LnJpY2huZXNzLnBkZiIpLAogICAgICAgd2lkdGggPSA1LAogICAgICAgaGVpZ2h0ID0gNSwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHAzLAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NlZ21lbnQucmljaG5lc3MucG5nIiksCiAgICAgICB3aWR0aCA9NSwKICAgICAgIGhlaWdodCA9IDUsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgpgYGB7cn0Kc2VnX3JpY2gkc2VnX3dlaWdodCA9IHBhc3RlMChzZWdfcmljaCRzZWdtZW50LCAnXycsIHNlZ19yaWNoJGZlcnJldF93ZWlnaHQpCnNlZ19yaWNoJGZlcnJldF93ZWlnaHQgPSBmYWN0b3Ioc2VnX3JpY2gkZmVycmV0X3dlaWdodCwgbGV2ZWxzID0gYygnc3RvY2snLCdsZWFuJywnb2Jlc2UnKSkKYGBgCgpgYGB7cn0Kc2VnX3JpY2ggJT4lIGZpbHRlcihzZWdtZW50ICVpbiUgU0VHTUVOVFMpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PXNlZ21lbnQsIHkgPSBzZWdfZGVsZXRpb25fcmljaG5lc3MsIGdyb3VwID0gc2VnX3dlaWdodCwgY29sb3IgPSBmZXJyZXRfd2VpZ2h0KSkgKyAKICAgIGdlb21fYm94cGxvdCgpICsgCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgd2VpZ2h0X2NvbFNjYWxlICsKICAgIGZhY2V0X2dyaWQoLn50eXBlKQoKCnA2ID0gc2VnX3JpY2ggJT4lIGZpbHRlcihzZWdtZW50ICVpbiUgU0VHTUVOVFMgJiBkcGkgJWluJSBjKCdkMDInLCdkMDQnLCdkMDYnLCdzdG9jaycpKSAlPiUKICAgIGZpbHRlcih0eXBlID09ICdpbmRleCcgfCB0eXBlID09ICJzdG9jayIpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PXNlZ21lbnQsIHkgPSBzZWdfZGVsZXRpb25fcmljaG5lc3MsIGdyb3VwID0gc2VnX3dlaWdodCwgY29sb3IgPSBmZXJyZXRfd2VpZ2h0KSkgKyAKICAgIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsgCiAgICBsYWJzKHg9J3NlZ21lbnQnLHk9J2RlbGV0aW9uIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgd2VpZ2h0X2NvbFNjYWxlICsKICAgIGZhY2V0X2dyaWQoLn5kcGkpCgpwcmludChwNikKCmdnc2F2ZShwNiwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zZWdtZW50LmluZGV4LnJpY2huZXNzLnBkZiIpLAogICAgICAgd2lkdGggPSA4LAogICAgICAgaGVpZ2h0ID0gNCwgbGltaXRzaXplPUZBTFNFLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQoKZ2dzYXZlKHA2LAogICAgICAgZmlsZW5hbWUgPSBnbHVlKCJ7d2tkaXJ9L0RWR19maWd1cmVzL3NlZ21lbnQuaW5kZXgucmljaG5lc3MucG5nIiksCiAgICAgICB3aWR0aCA9OCwKICAgICAgIGhlaWdodCA9IDQsIGxpbWl0c2l6ZT1GQUxTRSkgIywgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCgpgYGAKVGVzdCBmb3Igc2lnbmlmaWNhbmNlCmBgYHtyfQpvID0gZmlsdGVyKHNlZ19yaWNoLCB0eXBlID09ICJpbmRleCIgJiBkcGkgPT0gImQwMiIgJiBzZWdtZW50ID09ICJIOU4yX1BCMiIgJiBmZXJyZXRfd2VpZ2h0ID09ICJvYmVzZSIpCmwgPSBmaWx0ZXIoc2VnX3JpY2gsIHR5cGUgPT0gImluZGV4IiAmIGRwaSA9PSAiZDAyIiAmIHNlZ21lbnQgPT0gIkg5TjJfUEIyIiAmIGZlcnJldF93ZWlnaHQgPT0gImxlYW4iKQp0LnRlc3QobyRzZWdfZGVsZXRpb25fcmljaG5lc3MsbCRzZWdfZGVsZXRpb25fcmljaG5lc3MpCmBgYAoKYGBge3J9CnNlZ19yaWNoICU+JSBmaWx0ZXIodHlwZSA9PSAnaW5kZXgnICYgIHNlZ21lbnQgJWluJSBTRUdNRU5UUykgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICB1bmlxdWUoKSAlPiUKICAgIGdncGxvdCguLCBhZXMoeD10eXBlX2RheSwgeSA9IHNlZ19kZWxldGlvbl9yaWNobmVzcywgY29sb3IgPSBzZWdtZW50LCBncm91cD1zZWdtZW50KSkgKyAKICAgICNnZW9tX2JveHBsb3QoKSArIAogICAgZ2VvbV9saW5lKHNpemUgPSAxKSArIAogICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICAgIGxhYnMoeD0nZHBpIChieSBpbmRleCBjYXNlKScsIHk9J0RWRyByaWNobmVzcycpICsgCiAgICBQbG90VGhlbWUxICsKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gJ1NldDInKSArCiAgICAjd2VpZ2h0X2NvbFNjYWxlICsgCiAgICBmYWNldF9ncmlkKC5+ZmVycmV0X3dlaWdodCArIGZlcnJldF9pZCwgc2NhbGVzID0gJ2ZyZWUnLCBzcGFjZSA9ICdmcmVlJykKYGBgCgpgYGB7cn0KcDQgPSBzZWdfcmljaCAlPiUgZmlsdGVyKGZlcnJldF93ZWlnaHQgPT0gJ29iZXNlJyAmIGluZGV4X2RpcmVjdCA9PSAnb2Jlc2Vfb2Jlc2UnICYgc2VnbWVudCAlaW4lIFNFR01FTlRTKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgIHVuaXF1ZSgpICU+JQogICAgZ2dwbG90KC4sIGFlcyh4PXR5cGVfZGF5LCB5ID0gc2VnX2RlbGV0aW9uX3JpY2huZXNzLCBjb2xvciA9IHNlZ21lbnQsIGdyb3VwPXNlZ21lbnQpKSArIAogICAgI2dlb21fYm94cGxvdCgpICsgCiAgICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsgCiAgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAogICAgbGFicyh4PSdkcGkgKGJ5IGluZGV4IGNhc2UpJywgeT0nRFZHIHJpY2huZXNzJykgKyAKICAgIFBsb3RUaGVtZTEgKwogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAnU2V0MicpICsKICAgICN3ZWlnaHRfY29sU2NhbGUgKyAKICAgIGZhY2V0X2dyaWQoLn5wYWlyX2lkcywgc2NhbGVzID0gJ2ZyZWUnLCBzcGFjZSA9ICdmcmVlJykKCnByaW50KHA0KQoKCmdnc2F2ZShwNCwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zZWdtZW50Lm9iZXNlLnRvLm9iZXNlLnJpY2huZXNzLnBkZiIpLAogICAgICAgd2lkdGggPSAxMiwKICAgICAgIGhlaWdodCA9IDQsIGxpbWl0c2l6ZT1GQUxTRSwgdXNlRGluZ2JhdHMgPSBGQUxTRSkKCmdnc2F2ZShwNCwKICAgICAgIGZpbGVuYW1lID0gZ2x1ZSgie3drZGlyfS9EVkdfZmlndXJlcy9zZWdtZW50Lm9iZXNlLnRvLm9iZXNlLnJpY2huZXNzLnBuZyIpLAogICAgICAgd2lkdGggPTEyLAogICAgICAgaGVpZ2h0ID0gNCwgbGltaXRzaXplPUZBTFNFKSAjLCB1c2VEaW5nYmF0cyA9IEZBTFNFKQpgYGAKCkVuZCBvZiBLYXRlJ3MgY29kZQoKV2hpY2ggRFZHcyBhcmUgc2hhcmVkIGJldHdlZW4gc3RvY2sgYW5kIGluZGV4PwpgYGB7cn0KcmVwc19kZiREVkcgPSBwYXN0ZTAocmVwc19kZiRzZWdtZW50LCJfIixyZXBzX2RmJERWR19ncm91cCkKCkYxN19zdG9jayA9IGZpbHRlcihyZXBzX2RmICx0eXBlID09ICJzdG9jayIsIGNvaG9ydCA9PSAiRjE3IikKRjE3X3N0b2NrX2R2ZyA9IHVuaXF1ZShGMTdfc3RvY2skRFZHKQpXMTdfc3RvY2sgPSBmaWx0ZXIocmVwc19kZiAsdHlwZSA9PSAic3RvY2siLCBjb2hvcnQgPT0gIlcxNyIpClcxN19zdG9ja19kdmcgPSB1bmlxdWUoVzE3X3N0b2NrJERWRykKU20xOF9zdG9jayA9IGZpbHRlcihyZXBzX2RmICx0eXBlID09ICJzdG9jayIsIGNvaG9ydCA9PSAiU20xOCIpClNtMThfc3RvY2tfZHZnID0gdW5pcXVlKFNtMThfc3RvY2skRFZHKQpTcDE5X3N0b2NrID0gZmlsdGVyKHJlcHNfZGYgLHR5cGUgPT0gInN0b2NrIiwgY29ob3J0ID09ICJTcDE5IikKU3AxOV9zdG9ja19kdmcgPSB1bmlxdWUoU3AxOV9zdG9jayREVkcpClNwMjBfc3RvY2sgPSBmaWx0ZXIocmVwc19kZiAsdHlwZSA9PSAic3RvY2siLCBjb2hvcnQgPT0gIlNwMjAiKQpTcDIwX3N0b2NrX2R2ZyA9IHVuaXF1ZShTcDIwX3N0b2NrJERWRykKCkYxN19pbmRleCA9IGZpbHRlcihyZXBzX2RmICx0eXBlID09ICJpbmRleCIsIGNvaG9ydCA9PSAiRjE3IikKRjE3X2luZGV4X2R2ZyA9IHVuaXF1ZShGMTdfaW5kZXgkRFZHKQpXMTdfaW5kZXggPSBmaWx0ZXIocmVwc19kZiAsdHlwZSA9PSAiaW5kZXgiLCBjb2hvcnQgPT0gIlcxNyIpClcxN19pbmRleF9kdmcgPSB1bmlxdWUoVzE3X2luZGV4JERWRykKU20xOF9pbmRleCA9IGZpbHRlcihyZXBzX2RmICx0eXBlID09ICJpbmRleCIsIGNvaG9ydCA9PSAiU20xOCIpClNtMThfaW5kZXhfZHZnID0gdW5pcXVlKFNtMThfaW5kZXgkRFZHKQpTcDE5X2luZGV4ID0gZmlsdGVyKHJlcHNfZGYgLHR5cGUgPT0gImluZGV4IiwgY29ob3J0ID09ICJTcDE5IikKU3AxOV9pbmRleF9kdmcgPSB1bmlxdWUoU3AxOV9pbmRleCREVkcpClNwMjBfaW5kZXggPSBmaWx0ZXIocmVwc19kZiAsdHlwZSA9PSAiaW5kZXgiLCBjb2hvcnQgPT0gIlNwMjAiKQpTcDIwX2luZGV4X2R2ZyA9IHVuaXF1ZShTcDIwX2luZGV4JERWRykKCkYxN19zaGFyZWQgPSBGMTdfaW5kZXggJT4lIGZpbHRlcihEVkcgJWluJSBGMTdfc3RvY2tfZHZnKSAlPiUgZmlsdGVyKChEVkcgJWluJSBGMTdfaW5kZXhfZHZnKSkgJT4lIHVuaXF1ZSgpCkYxN19kZW5vdm8gPSBGMTdfaW5kZXggJT4lIGZpbHRlcigoRFZHICVpbiUgRjE3X2luZGV4X2R2ZykpICU+JSBmaWx0ZXIoIShEVkcgJWluJSBGMTdfc3RvY2tfZHZnKSkgJT4lIHVuaXF1ZSgpCgpXMTdfc2hhcmVkID0gVzE3X2luZGV4ICU+JSBmaWx0ZXIoRFZHICVpbiUgVzE3X3N0b2NrX2R2ZykgJT4lIGZpbHRlcigoRFZHICVpbiUgVzE3X2luZGV4X2R2ZykpICU+JSB1bmlxdWUoKQpXMTdfZGVub3ZvID0gVzE3X2luZGV4ICU+JSBmaWx0ZXIoKERWRyAlaW4lIFcxN19pbmRleF9kdmcpKSAlPiUgZmlsdGVyKCEoRFZHICVpbiUgVzE3X3N0b2NrX2R2ZykpICU+JSB1bmlxdWUoKQoKU20xOF9zaGFyZWQgPSBTbTE4X2luZGV4ICU+JSBmaWx0ZXIoRFZHICVpbiUgU20xOF9zdG9ja19kdmcpICU+JSBmaWx0ZXIoKERWRyAlaW4lIFNtMThfaW5kZXhfZHZnKSkgJT4lIHVuaXF1ZSgpClNtMThfZGVub3ZvID0gU20xOF9pbmRleCAlPiUgZmlsdGVyKChEVkcgJWluJSBTbTE4X2luZGV4X2R2ZykpICU+JSBmaWx0ZXIoIShEVkcgJWluJSBTbTE4X3N0b2NrX2R2ZykpICU+JSB1bmlxdWUoKQoKU3AxOV9zaGFyZWQgPSBTcDE5X2luZGV4ICU+JSBmaWx0ZXIoRFZHICVpbiUgU3AxOV9zdG9ja19kdmcpICU+JSBmaWx0ZXIoKERWRyAlaW4lIFNwMTlfaW5kZXhfZHZnKSkgJT4lIHVuaXF1ZSgpClNwMTlfZGVub3ZvID0gU3AxOV9pbmRleCAlPiUgZmlsdGVyKChEVkcgJWluJSBTcDE5X2luZGV4X2R2ZykpICU+JSBmaWx0ZXIoIShEVkcgJWluJSBTcDE5X3N0b2NrX2R2ZykpICU+JSB1bmlxdWUoKQoKU3AyMF9zaGFyZWQgPSBTcDIwX2luZGV4ICU+JSBmaWx0ZXIoRFZHICVpbiUgU3AyMF9zdG9ja19kdmcpICU+JSBmaWx0ZXIoKERWRyAlaW4lIFNwMjBfaW5kZXhfZHZnKSkgJT4lIHVuaXF1ZSgpICMgc3RpbGwgbm90IHdvcmtpbmcKU3AyMF9kZW5vdm8gPSBTcDIwX2luZGV4ICU+JSBmaWx0ZXIoKERWRyAlaW4lIFNwMjBfaW5kZXhfZHZnKSkgJT4lIGZpbHRlcighKERWRyAlaW4lIFNwMjBfc3RvY2tfZHZnKSkgJT4lIHVuaXF1ZSgpICMgc3RpbGwgbm90IHdvcmtpbmcKCnN0b2NrX3NoYXJlZCA9IHJiaW5kKEYxN19zaGFyZWQsVzE3X3NoYXJlZCxTbTE4X3NoYXJlZCxTcDE5X3NoYXJlZCxTcDIwX3NoYXJlZCkKaW5kZXhfdW5pcXVlID0gcmJpbmQoRjE3X2Rlbm92byxXMTdfZGVub3ZvLFNtMThfZGVub3ZvLFNwMTlfZGVub3ZvLFNwMjBfZGVub3ZvKQpgYGAKCmBgYHtyfQpzdG9ja19vYmVzZSA9IGZpbHRlcihzdG9ja19zaGFyZWQsIGZlcnJldF93ZWlnaHQgPT0gIm9iZXNlIikgCm9fZHZnID0gdW5pcXVlKHN0b2NrX29iZXNlJERWRykKCnN0b2NrX2xlYW4gPSBmaWx0ZXIoc3RvY2tfc2hhcmVkLCBmZXJyZXRfd2VpZ2h0ID09ICJsZWFuIikgCmxfZHZnID0gdW5pcXVlKHN0b2NrX2xlYW4kRFZHKQoKc3RvY2tfZHZnIDwtIGxpc3QoT2Jlc2UgPSBvX2R2ZywgTGVhbiA9IGxfZHZnKQoKU3RvY2tEVkdzID0gZ2dWZW5uRGlhZ3JhbShzdG9ja19kdmcpCnByaW50KFN0b2NrRFZHcykKZ2dzYXZlKFN0b2NrRFZHcywgZmlsZSA9ICJTdG9ja0RWR3MucGRmIiwgcGF0aCA9IHNhdmVpdGRpcikKClNob2NrU2hhcmVkRFZHcyA9IGdncGxvdChzdG9ja19zaGFyZWQsIGFlcyh4ID0gZHBpLCB5ID0gRFZHKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IERWRykpICsKICBmYWNldF9ncmlkKH5zZWdtZW50KSArCiAgUGxvdFRoZW1lMQpwcmludChTaG9ja1NoYXJlZERWR3MpCmdnc2F2ZShTaG9ja1NoYXJlZERWR3MsIGZpbGUgPSAiU2hvY2tTaGFyZWREVkdzLnBkZiIsIHBhdGggPSBzYXZlaXRkaXIpCmBgYApBcmUgdGhlcmUgZGlldC1zcGVjaWZpYyBEVkdzIGluIGluZGV4IGZlcnJldHM/CmBgYHtyfQppbmRleF9vYmVzZSA9IGZpbHRlcihpbmRleF91bmlxdWUsIGZlcnJldF93ZWlnaHQgPT0gIm9iZXNlIikgCm9fZHZnID0gdW5pcXVlKGluZGV4X29iZXNlJERWRykKCmluZGV4X2xlYW4gPSBmaWx0ZXIoaW5kZXhfdW5pcXVlLCBmZXJyZXRfd2VpZ2h0ID09ICJsZWFuIikgCmxfZHZnID0gdW5pcXVlKGluZGV4X2xlYW4kRFZHKQoKZGlldF9kdmcgPC0gbGlzdChPYmVzZSA9IG9fZHZnLCBMZWFuID0gbF9kdmcpCgpEaWV0VW5pcXVlRFZHcyA9IGdnVmVubkRpYWdyYW0oZGlldF9kdmcpCnByaW50KERpZXRVbmlxdWVEVkdzKQpnZ3NhdmUoRGlldFVuaXF1ZURWR3MsIGZpbGUgPSAiRGlldFVuaXF1ZURWR3MucGRmIiwgcGF0aCA9IHNhdmVpdGRpcikKYGBgCgpQdWxsaW5nIG91dCBkaWV0LXNwZWNpZmljIERWR3MKYGBge3J9CmxlYW4gPSBpbmRleF9sZWFuICU+JSAKICBmaWx0ZXIoRFZHICVpbiUgbF9kdmcpICU+JSAKICBmaWx0ZXIoIShEVkcgJWluJSBvX2R2ZykpICU+JQogIHVuaXF1ZSgpCgpsZWFuID0gbGVhbiAlPiUKICBncm91cF9ieShEVkcpICU+JSAKICBtdXRhdGUoY291bnQgPSAxLCB0b3RhbHNhbXAgPSBzdW0oY291bnQpKQoKbXVsdF9sZWFuID0gZmlsdGVyKGxlYW4sIHRvdGFsc2FtcCA+IDEpICU+JSAKICB1bmlxdWUoKQoKb2Jlc2UgPSBpbmRleF91bmlxdWUgJT4lIAogIGZpbHRlcigoRFZHICVpbiUgb19kdmcpKSAlPiUKICBmaWx0ZXIoIShEVkcgJWluJSBsX2R2ZykpICU+JSAKICB1bmlxdWUoKQoKb2Jlc2UgPSBvYmVzZSAlPiUKICBncm91cF9ieShEVkcpICU+JSAKICBtdXRhdGUoY291bnQgPSAxLCB0b3RhbHNhbXAgPSBzdW0oY291bnQpKQoKbXVsdF9vYmVzZSA9IGZpbHRlcihvYmVzZSwgdG90YWxzYW1wID4gMSkgJT4lIAogIHVuaXF1ZSgpCmBgYAoKYGBge3J9CmxlYW5fdW5pcXVlcyA9IGxlYW4gJT4lCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3Qoc2VnbWVudCxEVkdfZ3JvdXAsR3JvdXBCb3VuZGFyaWVzLHRvdGFsc2FtcCkgJT4lIAogIHVuaXF1ZSgpICU+JSAKICBhcnJhbmdlKGRlc2ModG90YWxzYW1wKSkKcHJpbnQobGVhbl91bmlxdWVzKQoKb2Jlc2VfdW5pcXVlcyA9IG9iZXNlICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgc2VsZWN0KHNlZ21lbnQsRFZHX2dyb3VwLEdyb3VwQm91bmRhcmllcyx0b3RhbHNhbXApICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgYXJyYW5nZShkZXNjKHRvdGFsc2FtcCkpCnByaW50KG9iZXNlX3VuaXF1ZXMpCmBgYAoKQXJlIERWR3MgdHJhbnNtaXR0ZWQ/CmBgYHtyfQpkdmdfZGYgPSBzZWxlY3QocmVwc19kZiwgZmVycmV0X2RheSwgZmVycmV0X2lkLCBkcGksIGZlcnJldF93ZWlnaHQsIHR5cGUsIHNlZ21lbnQsIERWR19ncm91cCwgR3JvdXBCb3VuZGFyaWVzLCBwYWlyLCBpbmRleF9kaXJlY3QsIHBhaXJfaWRzKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgdW5pcXVlKCkKZHZnX2RmJHNlZ19kdmcgPSBwYXN0ZTAoZHZnX2RmJHNlZ21lbnQsIl8iLGR2Z19kZiREVkdfZ3JvdXApCgppbmRleCA9IGZpbHRlcihkdmdfZGYsIHR5cGUgPT0gImluZGV4IikgJT4lIHVuaXF1ZSgpCmZpcnN0X3RpbWUgPSBjKCIxNzk0X2QwNCIsIjE3OTdfZDAyIiwiMTkxM19kMDYiLCIxOTE0X2QwNiIsIjE5ODBfZDAyIiwiMTk4MV9kMTAiLCIxOTg2X2QxMCIsIjIyMzFfZDA2IiwiMjIzMl9kMDIiLCIyMjM5X2QwMiIpCmVhcmx5X3RpbWUgPSBjKCIxNzk0X2QwNCIsIjE3OTdfZDAyIiwiMTk4MF9kMDIiLCIyMjMyX2QwMiIsIjIyMzlfZDAyIikKZGlyZWN0ID0gZmlsdGVyKGR2Z19kZiwgZmVycmV0X2RheSAlaW4lIGZpcnN0X3RpbWUpICU+JSB1bmlxdWUoKQogCnNhbXBsZXMgPSB1bmlxdWUoaW5kZXgkZmVycmV0X2RheSkKICAKZHZnX3RyYW5zbWl0dGVkID0gZGF0YS5mcmFtZSgpCiAgCmZvcihpIGluIHNhbXBsZXMpewogIHByaW50KGkpCiAgCiAgbiA9IGZpbHRlcihpbmRleCwgZmVycmV0X2RheSA9PSBpKQogIHBhcnRuZXIgPSB1bmlxdWUobiRwYWlyX2lkcykKICBkID0gZmlsdGVyKGRpcmVjdCwgcGFpcl9pZHMgJWluJSBwYXJ0bmVyKQogIAogIGlmKG5yb3coZCkgPiAwKXsKICAgIAogICAgcyA9IHVuaXF1ZShkJGZlcnJldF9kYXkpCiAgICBwcmludChzKQogIAogICAgY29tcCA9IG1lcmdlKG4sIGQsIGJ5ID0gYygiaW5kZXhfZGlyZWN0IiwicGFpcl9pZHMiLCJwYWlyIiwic2VnbWVudCIsInNlZ19kdmciLCJEVkdfZ3JvdXAiLCJHcm91cEJvdW5kYXJpZXMiKSwgYWxsLnggPSBUUlVFKSAlPiUKICAgICAgY291bnQocGFpcl9pZHMsZmVycmV0X2RheS54LCBmZXJyZXRfZGF5LnkpCiAgICBjb2xuYW1lcyhjb21wKSA9IGMoInBhaXJfaWRzIiwiaW5kZXgiLCJjb250YWN0IiwiY291bnQiKQogICAgIAogICAgZHZnX3RyYW5zbWl0dGVkID0gcmJpbmQoZHZnX3RyYW5zbWl0dGVkLCBjb21wKQogICAKICB9ZWxzZShwcmludCgiTm8gdHJhbnNtaXNzaW9uIikpCiAgCn0KCiNkdmdfdHJhbnNtaXR0ZWQgPSBkdmdfdHJhbnNtaXR0ZWQgJT4lIAojICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gY29udGFjdCwgdmFsdWVzX2Zyb20gPSBjb3VudCkKYGBgCgpgYGB7cn0KIGNvbnRhY3RfZHZncyA9IGZpbHRlcihkdmdfZGYsIHR5cGUgPT0gImRpcmVjdCIpICU+JSBjb3VudChmZXJyZXRfaWQsZHBpLGZlcnJldF93ZWlnaHQpICU+JQogIGdncGxvdCguLCBhZXMoeCA9IGRwaSwgeSA9IG4sIGNvbG9yID0gZmVycmV0X3dlaWdodCkpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBmZXJyZXRfaWQpKSArCiAgZmFjZXRfZ3JpZCh+ZmVycmV0X2lkKSArCiAgeWxhYigiRFZHIHJpY2huZXNzIikgKwogIHhsYWIoIkRQSSIpICsKICBQbG90VGhlbWUxICsKICB3ZWlnaHRfY29sU2NhbGUKcHJpbnQoY29udGFjdF9kdmdzKQpnZ3NhdmUoY29udGFjdF9kdmdzLCBmaWxlID0gImNvbnRhY3RfZHZncy5wZGYiLCBwYXRoID0gc2F2ZWl0ZGlyKQpgYGAK